排他制御

C#でスレッドの排他ロックを行う場合、次のようにすれば、スコープ内は排他制御されます。

    lock (this)
    {
    }

WindowsC++で、「排他制御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;
}