Ich denke, ich habe was du suchst. Es ist eine Lock-freie Ringpuffer-Implementierung, die den Producer/Consumer blockiert. Sie benötigen nur Zugriff auf atomare Primitive - in diesem Beispiel verwende ich die sync
-Funktionen von gcc.
Es hat einen bekannten Fehler - wenn Sie den Puffer um mehr als 100% überlaufen, ist es nicht garantiert, dass die Warteschlange FIFO bleibt (es wird immer noch alle sie schließlich verarbeiten).
Diese Implementierung basiert auf Lesen/als eine atomare Operation die Pufferelemente zu schreiben (was ziemlich viel für Zeiger garantiert)
struct ringBuffer
{
void** buffer;
uint64_t writePosition;
size_t size;
sem_t* semaphore;
}
//create the ring buffer
struct ringBuffer* buf = calloc(1, sizeof(struct ringBuffer));
buf->buffer = calloc(bufferSize, sizeof(void*));
buf->size = bufferSize;
buf->semaphore = malloc(sizeof(sem_t));
sem_init(buf->semaphore, 0, 0);
//producer
void addToBuffer(void* newValue, struct ringBuffer* buf)
{
uint64_t writepos = __sync_fetch_and_add(&buf->writePosition, 1) % buf->size;
//spin lock until buffer space available
while(!__sync_bool_compare_and_swap(&(buf->buffer[writePosition]), NULL, newValue));
sem_post(buf->semaphore);
}
//consumer
void processBuffer(struct ringBuffer* buf)
{
uint64_t readPos = 0;
while(1)
{
sem_wait(buf->semaphore);
//process buf->buffer[readPos % buf->size]
buf->buffer[readPos % buf->size] = NULL;
readPos++;
}
}
Ich weiß nicht, in welcher Umgebung Sie sich befinden, aber in Win32 können Sie WaitForMultipleObjects verwenden, damit der Konsument in allen Warteschlangen gleichzeitig wartet, ohne sich zu drehen. –
Es tut mir leid, ich habe nicht erwähnt, dass ich hauptsächlich an Linux arbeite – ziu
Nur für den Fall, dass Sie keine echte Antwort erhalten, wird es ein Kinderspiel, mehrere Puffer mit diesem zu synchronisieren: http://neosmart.net/ blog/2011/waitformultipleobjects-and-win32-events-for-linux-und-lesen-schreiben-locks-for-windows/ –