After having read this wonderful article, I starting digging around to volatile-correct some code. One consequence of volatile-correctness (as I understand it) is that methods accessed from different threads should be volatile qualified.
A simple example might be a mutex using Win32 or pthreads. We could make a class Mutex
and give it a field:
#if defined BACKEND_WIN32
CRITICAL_SECTION _lock;
#elif defined BACKEND_POSIX
pthread_mutex_t _lock;
#endif
The ".acquire()" method might look like:
void Mutex::acquire(void) volatile {
#if defined BACKEND_WIN32
EnterCriticalSection(&_lock);
#elif defined BACKEND_POSIX
pthread_mutex_lock(&_lock);
#endif
}
Trying this doesn't work. From MSVC:
error C2664: 'void EnterCriticalSection(LPCRITICAL_SECTION)' : cannot convert argument 1 from 'volatile CRITICAL_SECTION *' to 'LPCRITICAL_SECTION'
From g++:
error: invalid conversion from ‘volatile pthread_mutex_t*’ to ‘pthread_mutex_t*’ [-fpermissive]
You'll get similar problems trying to unlock _lock
. Two questions:
- My impression is that these are just artifacts of the APIs being outdated. Is this in fact the case? Did I misunderstand something?
- The whole purpose of a lock or unlock API function is to switch between being in a critical section, therefore, is it the case that I should just use the inadequately named
const_cast
to cast away thevolatile
-ness of_lock
before passing to these functions, with no ill effect?