Win32 альтернатива pthread

Можно ли написать это, используя стандартный код стиля win32 CreateMutex. Мне просто интересно, хочу ли я добавить новую библиотеку в наше приложение или я могу найти способ написать это сам. Я просто не могу понять, как ждать внутри CriticalSection. Это мой текущий рабочий код с библиотекой pthread.

T remove() {
pthread_mutex_lock(&m_mutex);
while (m_queue.size() == 0) {
pthread_cond_wait(&m_condv, &m_mutex);
}
T item = m_queue.front();
m_queue.pop_front();
pthread_mutex_unlock(&m_mutex);
return item;
}

0

Решение

Вот моя попытка. Это не лучшая реализация условной блокировки ожидания в win32, но я думаю, что она работает. Он может использовать тщательный анализ кода.

Одно предупреждение — это не обязательно гарантирует порядочную справедливость, поскольку все ожидающие потоки могут быть первоначально заблокированы в ожидании события. Планировщик возобновит все потоки в этот момент, чтобы продолжить работу (вплоть до последующего блокирующего вызова EnterCriticalSection), но не обязательно в том же порядке, в котором потоки поступили в вызов remove () для начала. Это, вероятно, не имеет большого значения для большинства приложений с небольшим количеством потоков, но это то, что большинство потоковых сред гарантируют.

Другое предостережение — для краткости я пропускаю важные этапы проверки возвращаемого значения из всех этих Win32 API.

CRITICAL_SECTION m_cs;
HANDLE m_event;

void Init()
{
InitializeCriticalSection(&m_cs);
m_event = CreateEvent(NULL, TRUE, FALSE, NULL); // manual reset event
}

void UnInit()
{
DeleteCriticalSection(&m_cs);
CloseHandle(m_event);
m_event = NULL;
}

T remove()
{
T item;
bool fGotItem = false;
while (fGotItem == false)
{
// wait for event to be signaled
WaitForSingleObject(m_event, INFINITE);

// wait for mutex to become available
EnterCriticalSection(&m_cs);

// inside critical section
{
// try to deque something - it’s possible that the queue is empty because another
// thread pre-empted us and got the last item in the queue before us

size_t queue_size = m_queue.size();

if (queue_size == 1)
{
// the queue is about to go empty
ResetEvent(m_event);
}

if (queue_size > 0)
{
fGotItem = true;
item = m_queue.front();

m_queue.pop();
}
}

LeaveCriticalSection(&m_cs);

}

return item;
}

void Add(T& item)
{
// wait for critical section to become available
EnterCriticalSection(&m_cs);

// inside critical section
{
m_queue.push_back(item);

SetEvent(m_event); // signal other threads that something is available
}

LeaveCriticalSection(&m_cs);
}
2

Другие решения

Для поддержки до VC-2012 лучшая альтернатива Boost.Thread который поддерживает условные переменные.

3

Windows Vista представила новый родной Win32 Условная переменная а также Тонкий замок для чтения / записи примитивы именно для этого типа сценария, например:

Использование критического раздела:

CRITICAL_SECTION m_cs;
CONDITION_VARIABLE m_condv;

InitializeCriticalSection(&m_cs);
InitializeConditionVariable(&m_condv);

...

void add(T item)
{
EnterCriticalSection(&m_cs);
m_queue.push_back(item);
LeaveCriticalSection(&m_cs);
WakeConditionVariable(&m_condv);
}

T remove()
{
EnterCriticalSection(&m_cs);
while (m_queue.size() == 0)
SleepConditionVariableCS(&m_condv, &m_cs, INFINITE);
T item = m_queue.front();
m_queue.pop_front();
LeaveCriticalSection(&m_cs);
return item;
}

Использование блокировки SRW:

SRWLOCK m_lock;
CONDITION_VARIABLE m_condv;

InitializeSRWLock(&m_lock);
InitializeConditionVariable(&m_condv);

...

void add(T item)
{
AcquireSRWLockExclusive(&m_lock);
m_queue.push_back(item);
ReleaseSRWLockExclusive(&m_lock);
WakeConditionVariable(&m_condv);
}

T remove()
{
AcquireSRWLockExclusive(&m_lock);
while (m_queue.size() == 0)
SleepConditionVariableSRW(&m_condv, &m_lock, INFINITE, 0);
T item = m_queue.front();
m_queue.pop_front();
ReleaseSRWLockExclusive(&m_lock);
return item;
}
1
По вопросам рекламы [email protected]