У меня проблема с производителем-потребителем для решения с небольшими изменениями - существует много параллельных производителей, но только один потребитель в одной параллельной нити. Когда производителю нет места в буфере, он просто игнорирует элемент (не дожидаясь потребителя). У меня есть несколько писем C:Практически беззаконный потребитель-производитель
struct Element
{
ULONG content;
volatile LONG bNew;
}
ULONG max_count = 10;
Element buffer* = calloc(max_count, sizeof(Element));
volatile LONG producer_idx = 0;
LONG consumer_idx = 0;
EVENT NotEmpty;
BOOLEAN produce(ULONG content)
{
LONG idx = InterlockedIncrement(&consumer_idx) % max_count;
if(buffer[idx].bNew)
return FALSE;
buffer[idx].content = content;
buffer[idx].bNew = TRUE;
SetEvent(NotEmpty);
return TRUE;
}
void consume_thread()
{
while(TRUE)
{
Wait(NotEmpty);
while(buffer[consumer_idx].bNew)
{
ULONG content = buffer[consumer_idx].content;
InterlockedExchange(&buffer[consumer_idx].bNew, FALSE);
//Simple mechanism for preventing producer_idx overflow
LONG tmp = producer_idx;
InterlockedCompareExchange(&producer_idx, tmp%maxcount, tmp);
consumer_idx = (consumer_idx+1)%max_count;
doSth(content);
}
}
}
Я не уверен, что этот код верен на 100%. Можете ли вы увидеть какие-либо проблемы, которые могут возникнуть? Или, может быть, этот код может быть написан лучше?
Я использую глобальные переменные и атомарные операции для выполнения синхронизации беззамочной. Это по соображениям производительности. – rnd
Ну ... на самом деле у вас есть только инкремент. У вас все еще есть буфер [i] .bNew грязный. На мой взгляд, использование единого семафора - это лучшая идея, а не назначение производителей одному индексу узла массива. – SOReader