|
//////////////////////////////////////////////////////////////////////////
//
// Author - Oleg Fedchenko
//
// www.MulticoreWinsoft.com
//
//////////////////////////////////////////////////////////////////////////
#pragma once
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
//////////////////////////////////////////////////////////////////////////
template<typename T>
class CThreadPtr
{
public:
class CLocker : public boost::noncopyable
{
public:
CLocker(const CThreadPtr& threadPtr)
:m_threadPtr( threadPtr)
{
::WaitForSingleObject( m_threadPtr.m_mutexInternal, INFINITE);
if (m_threadPtr.m_mutexObj)
::WaitForSingleObject( m_threadPtr.m_mutexObj, INFINITE);
}
~CLocker()
{
if (m_threadPtr.m_mutexObj)
::ReleaseMutex( m_threadPtr.m_mutexObj);
::ReleaseMutex( m_threadPtr.m_mutexInternal);
}
T& operator*() const
{
return *m_threadPtr.m_obj;
}
T* operator->() const
{
return &*m_threadPtr.m_obj;
}
private:
const CThreadPtr<T>& m_threadPtr;
};
public:
CThreadPtr() : m_mutexInternal(::CreateMutex(NULL, FALSE, NULL)),
m_mutexObj(0),
m_obj(){}
CThreadPtr(T* obj) : m_mutexInternal(::CreateMutex(NULL, FALSE, NULL)),
m_mutexObj(::CreateMutex(NULL, FALSE, NULL)),
m_obj(obj){}
CThreadPtr(const CThreadPtr& rh) : m_mutexInternal(::CreateMutex(NULL, FALSE, NULL)),
m_mutexObj(0),
m_obj()
{
if (::WaitForSingleObject( rh.m_mutexInternal, INFINITE) == WAIT_OBJECT_0)
{
// copy if rh is not destroyed
if (rh.m_mutexObj)
{
::WaitForSingleObject( rh.m_mutexObj, INFINITE);
if (DuplicateHandle( rh.m_mutexObj, &m_mutexObj))
{
m_obj = rh.m_obj;
}
::ReleaseMutex( rh.m_mutexObj);
}
::ReleaseMutex( rh.m_mutexInternal);
}
}
~CThreadPtr()
{
::WaitForSingleObject( m_mutexInternal, INFINITE);
if (m_mutexObj)
{
::WaitForSingleObject( m_mutexObj, INFINITE);
m_obj.reset();
::CloseHandle(m_mutexObj);
m_mutexObj = 0;
}
::CloseHandle(m_mutexInternal);
}
CThreadPtr& operator=(const CThreadPtr& rh)
{
// do not copy myself
if (&rh == this)
return *this;
::WaitForSingleObject( m_mutexInternal, INFINITE);
// clear my obj
if (m_mutexObj)
{
::WaitForSingleObject( m_mutexObj, INFINITE);
m_obj.reset();
::CloseHandle(m_mutexObj);
m_mutexObj = 0;
}
// copy if rh is not destroyed
if (::WaitForSingleObject( rh.m_mutexInternal, INFINITE) == WAIT_OBJECT_0)
{
// copy if not null
if (rh.m_mutexObj)
{
::WaitForSingleObject( rh.m_mutexObj, INFINITE);
if (DuplicateHandle( rh.m_mutexObj, &m_mutexObj))
{
m_obj = rh.m_obj;
}
::ReleaseMutex( rh.m_mutexObj);
}
::ReleaseMutex( rh.m_mutexInternal);
}
::ReleaseMutex( m_mutexInternal);
return *this;
}
CLocker operator->() const
{
return *this;
}
CLocker operator*() const
{
return *this;
}
void reset()
{
::WaitForSingleObject( m_mutexInternal, INFINITE);
if (m_mutexObj)
{
::WaitForSingleObject( m_mutexObj, INFINITE);
m_obj.reset();
::CloseHandle(m_mutexObj);
m_mutexObj = 0;
}
::ReleaseMutex( m_mutexInternal);
}
void reset(T* obj)
{
::WaitForSingleObject( m_mutexInternal, INFINITE);
if (m_mutexObj)
::WaitForSingleObject( m_mutexObj, INFINITE);
m_obj.reset(obj);
// new mutex for a new obj
if (m_mutexObj)
::CloseHandle(m_mutexObj);
m_mutexObj = ::CreateMutex(NULL, FALSE, NULL);
//
::ReleaseMutex( m_mutexInternal);
}
operator bool () const
{
CLocker lock(*this);
return (bool)m_obj;
}
bool operator! () const
{
CLocker lock(*this);
return !m_obj;
}
private:
static bool DuplicateHandle( HANDLE src, HANDLE* dest)
{
HANDLE curProcess = ::GetCurrentProcess();
return ::DuplicateHandle(
curProcess, //HANDLE hSourceProcessHandle,
src, //HANDLE hSourceHandle,
curProcess, //HANDLE hTargetProcessHandle,
dest, //LPHANDLE lpTargetHandle,
0, //DWORD dwDesiredAccess, // ignored
FALSE, //BOOL bInheritHandle,
DUPLICATE_SAME_ACCESS //DWORD dwOptions
) == TRUE;
}
private:
HANDLE m_mutexInternal;
HANDLE m_mutexObj;
boost::shared_ptr<T> m_obj;
};
//////////////////////////////////////////////////////////////////////////
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.