May volatile be in user defined types to help writing thread-safe code
Posted
by David Rodríguez - dribeas
on Stack Overflow
See other posts from Stack Overflow
or by David Rodríguez - dribeas
Published on 2010-03-22T10:43:26Z
Indexed on
2010/03/22
11:21 UTC
Read the original article
Hit count: 381
I know, it has been made quite clear in a couple of questions/answers before, that volatile
is related to the visible state of the c++ memory model and not to multithreading.
On the other hand, this article by Alexandrescu uses the volatile
keyword not as a runtime feature but rather as a compile time check to force the compiler into failing to accept code that could be not thread safe. In the article the keyword is used more like a required_thread_safety
tag than the actual intended use of volatile
.
Is this (ab)use of volatile
appropriate? What possible gotchas may be hidden in the approach?
The first thing that comes to mind is added confusion: volatile
is not related to thread safety, but by lack of a better tool I could accept it.
Basic simplification of the article:
If you declare a variable volatile
, only volatile
member methods can be called on it, so the compiler will block calling code to other methods. Declaring an std::vector
instance as volatile
will block all uses of the class. Adding a wrapper in the shape of a locking pointer that performs a const_cast
to release the volatile
requirement, any access through the locking pointer will be allowed.
Stealing from the article:
template <typename T>
class LockingPtr {
public:
// Constructors/destructors
LockingPtr(volatile T& obj, Mutex& mtx)
: pObj_(const_cast<T*>(&obj)), pMtx_(&mtx)
{ mtx.Lock(); }
~LockingPtr() { pMtx_->Unlock(); }
// Pointer behavior
T& operator*() { return *pObj_; }
T* operator->() { return pObj_; }
private:
T* pObj_;
Mutex* pMtx_;
LockingPtr(const LockingPtr&);
LockingPtr& operator=(const LockingPtr&);
};
class SyncBuf {
public:
void Thread1() {
LockingPtr<BufT> lpBuf(buffer_, mtx_);
BufT::iterator i = lpBuf->begin();
for (; i != lpBuf->end(); ++i) {
// ... use *i ...
}
}
void Thread2();
private:
typedef vector<char> BufT;
volatile BufT buffer_;
Mutex mtx_; // controls access to buffer_
};
© Stack Overflow or respective owner