멀티스레드에 안전해지자.

2007/11/07 20:10

- CriticalSection 의 Enter, Leave 를 지역변수로 선언하여 데드락을 피하는 클래스

1.  CRITICAL_SECTION의 기능형 클래스
#pragma once

class CCriticalSection
{
public:
    CCriticalSection(VOID)
    {
        InitializeCriticalSection(&mSync);
    }

    ~CCriticalSection(VOID)
    {
        DeleteCriticalSection(&mSync);
    }

    inline VOID Enter(VOID)
    {
        EnterCriticalSection(&mSync);
    }

    inline VOID Leave(VOID)
    {
        LeaveCriticalSection(&mSync);
    }

private:
    CRITICAL_SECTION    mSync;
};

2. Enter, Leave를 지역변수화.
#pragma once

template <class T>
class CMultiThreadSync
{
friend class CThreadSync;
public:
    class CThreadSync
    {
    public:
        CThreadSync(VOID)
        {
            T::mSync.Enter();
        }

        ~CThreadSync(VOID)
        {
            T::mSync.Leave();
        }
    };

private:
    static CCriticalSection mSync;
};

template <class T>
CCriticalSection CMultiThreadSync<T>::mSync;


- 사용 예제 ( 메모리 풀 )
[ more.. | less.. ]
#pragma once

template <class T, int ALLOC_BLOCK_SIZE = 50>
class CMemoryPool : public CMultiThreadSync<T>
{
public:
    static VOID* operator new(std::size_t allocLength)
    {
        CThreadSync Sync;

        assert(sizeof(T) == allocLength);
        assert(sizeof(T) >= sizeof(UCHAR*));

        if (!mFreePointer)
            allocBlock();

        UCHAR *ReturnPointer = mFreePointer;
        mFreePointer = *reinterpret_cast<UCHAR**>(ReturnPointer);

        return ReturnPointer;
    }

    static VOID    operator delete(VOID* deletePointer)
    {
        CThreadSync Sync;

        *reinterpret_cast<UCHAR**>(deletePointer) = mFreePointer;
        mFreePointer = static_cast<UCHAR*>(deletePointer);
    }

private:
    static VOID    allocBlock()
    {
        mFreePointer        = new UCHAR[sizeof(T) * ALLOC_BLOCK_SIZE];

        UCHAR **Current = reinterpret_cast<UCHAR **>(mFreePointer);
        UCHAR *Next        = mFreePointer;

        for (INT i=0;i<ALLOC_BLOCK_SIZE-1;++i)
        {
            Next        += sizeof(T);
            *Current    = Next;
            Current        = reinterpret_cast<UCHAR**>(Next);
        }

        *Current = 0;
    }

private:
    static UCHAR    *mFreePointer;

protected:
    ~CMemoryPool()
    {
    }
};

template <class T, int ALLOC_BLOCK_SIZE>
UCHAR* CMemoryPool<T, ALLOC_BLOCK_SIZE>::mFreePointer;



Tags

CriticalSection, 멀티스레드