排他制御
C#でスレッドの排他ロックを行う場合、次のようにすれば、スコープ内は排他制御されます。
lock (this) { }
WindowsのC++で、「排他制御をC#風にできないか?」をテーマに実装してみました。
結果、こんな感じになりました。
#include <Windows.h> class CLockObject { protected: class CAutoLock { private: CRITICAL_SECTION *m_pLock; public: CAutoLock(CLockObject *pLock) : m_pLock((CRITICAL_SECTION*)*pLock) { EnterCriticalSection(m_pLock); } virtual ~CAutoLock(void) { LeaveCriticalSection(m_pLock); } }; #define lock(x) volatile CAutoLock lock( (x) ); private: CRITICAL_SECTION m_Lock; public: CLockObject(void) { InitializeCriticalSection(&m_Lock); } operator CRITICAL_SECTION*() { return &m_Lock; } virtual ~CLockObject(void) { DeleteCriticalSection(&m_Lock); } };
クラスはCLockObjectから派生すれば、多少違うけれど、同じように利用できるようになります。
lockをマクロで置き換えて、CAutoLockのインスタンスと置き換えてます。
スコープに入ると、CAutoLockのコンストラクタにより、ロックを取得。
逆にスコープを抜けると、CAutoLockのインスタンスが破棄されるので、デストラクタによりアンロックされます。
C#と同じように利用するには、lockを{}で囲う必要がありますが、似た感覚で利用できるのではないでしょうか?
class CTest : public CLockObject { private: int i; public: CTest(void) : i(0) { } void Print() { { lock(this) { printf("%d\n", i++); } } } }; CTest *g_test = new CTest(); DWORD CALLBACK ThreadProc(LPVOID param) { for(int i = 0; i< 100; i++) { g_test->Print(); } return 0; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hThread1 = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); HANDLE hThread2 = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); HANDLE hThread3 = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); WaitForSingleObject(hThread1, INFINITE); WaitForSingleObject(hThread2, INFINITE); WaitForSingleObject(hThread3, INFINITE); CloseHandle(hThread1); CloseHandle(hThread2); CloseHandle(hThread3); return 0; }