Re[3]: CriticalSection без конструктора
От: Блудов Павел Россия  
Дата: 27.01.03 06:18
Оценка:
Здравствуйте, AssAsin, Вы писали:

AA> Вы можете реализовать такое же поведение, работая с RTL_CRITICAL_SECTION?


В Вашем конкретном примере это вполне возможно. Примерно так:

struct MyCS
{
    CRITICAL_SECTION m_cs;
    HANDLE _TearoffSemaphore();

    void Enter();
    bool TryEnter();
    void Leave();

};

void MyCS::Enter()
{
    if (::InterlockedIncrement(&m_cs.LockCount))
    {
        if (m_cs.OwningThread == (HANDLE)::GetCurrentThreadId())
        {
            m_cs.RecursionCount++;
            return;
        }

        ::WaitForSingleObject(_TearoffSemaphore(), INFINITE);
    }

    m_cs.OwningThread = (HANDLE)::GetCurrentThreadId();
    m_cs.RecursionCount = 1;
}

bool MyCS::TryEnter()
{
    if (-1L == ::InterlockedCompareExchange(&m_cs.LockCount, 0, -1))
    {
        m_cs.OwningThread = (HANDLE)::GetCurrentThreadId();
        m_cs.RecursionCount = 1;
    }
    else if (m_cs.OwningThread == (HANDLE)::GetCurrentThreadId())
    {
        ::InterlockedIncrement(&m_cs.LockCount);
        m_cs.RecursionCount++;
    }
    else
        return FALSE;

    return TRUE;
}

void MyCS::Leave()
{
    if (--m_cs.RecursionCount)
        ::InterlockedDecrement(&m_cs.LockCount);
    else if (::InterlockedDecrement(&m_cs.LockCount) >= 0)
        ::ReleaseSemaphore(_TearoffSemaphore(), 1, NULL);
}

HANDLE MyCS::_TearoffSemaphore()
{
    HANDLE ret = m_cs.LockSemaphore;
    if (!ret)
    {
        HANDLE sem = ::CreateSemaphore(NULL, 0, 1, NULL);

        ret = (HANDLE)::InterlockedCompareExchangePointer(&m_cs.LockSemaphore, sem, NULL);
        if (!ret)
            ret = sem;
        else
            ::CloseHandle(sem);
    }
    return ret;
}

#define DEFINE_STATIC_MyCriticalSection(name) \
    static MyCS name = { {NULL, -1, 0, 0, NULL, 0}};

DEFINE_STATIC_MyCriticalSection(testCS);


т.е. основная идея в том, что

1. Initialize делает за нас компилятор (впрочем, это как раз Ваша мысль)
2. Используются самодельные Enter/TryEnter/Leave — гарантия того, что код
будет работать и на 9.x/Me

Надеюсь, это будет кому-либо полезно,
Павел.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.