Здравствуйте, 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
Надеюсь, это будет кому-либо полезно,
Павел.