понедельник, 26 января 2009 г.

LockingPtr and volatile - Multithreaded Programmer's Best Friends

There is a great article of Andrei Alexandrescu "volatile - Multithreaded Programmer's Best Friend" (russian version).

Here it is! Our Smart Friend:
template <typename T, typename Mutex = CSyncObject>
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&);
};


"In spite of its simplicity, LockingPtr is a very useful aid in writing correct multithreaded code. You should define objects that are shared between threads as volatile and never use const_cast with them — always use LockingPtr automatic objects."

Here is an example:
bRes = Write(strParams);
if (bRes)
{
tmTimer.Begin();
stWait( (bRes = sName[LD_Printer] == strReceived) ||
(bTimeout = tmTimer.isTimeout(_Settings.dwTimeout) == TRUE ) );

{
LockingPtr<TStringList> lpDocCVS(_DocCVS, _csLock);
if (!lpDocCVS->empty())
lpDocCVS->pop_front();
}

if (!bRes && bTimeout)
{
_Log.TWriteLn("!! TIMEOUT !!");
}
}

Комментариев нет:

Отправить комментарий