Een ringbuffer (ring buffer, circular buffer) wordt vaak gebruikt in systemen met beperkte geheugen, apparaatstuurprogramma's, netwerken en multitasking-systemen. Het concept werd al in de vroege stadia van de ontwikkeling van besturingssystemen gebruikt, toen het belangrijk was om het geheugen optimaal te gebruiken en geen middelen te verspillen aan het verschuiven van elementen na extractie.
Typische moeilijkheden zijn de correcte behandeling van de voorwaarden "buffer vol" en "buffer leeg", gebrek aan bescherming tegen overschrijven van gegevens, en gecompliceerde synchronisatie bij multithreading. Fouten kunnen optreden bij verwarring van grenzen en onjuiste indexcontroles.
Een ringbuffer-object wordt geïmplementeerd als een array met twee indexen (head en tail) en, indien nodig, een teller of extra logica om de staten "vol" en "leeg" te onderscheiden. Lezen en schrijven gebeurt modulo de grootte van de buffer.
#define BUF_SIZE 8 char buffer[BUF_SIZE]; int head = 0, tail = 0; // head – schrijven, tail – lezen // Schrijven if (((head + 1) % BUF_SIZE) != tail) { buffer[head] = data; head = (head + 1) % BUF_SIZE; } else { // Buffer vol } // Lezen if (head != tail) { char d = buffer[tail]; tail = (tail + 1) % BUF_SIZE; }
Belangrijke kenmerken:
Hoe een volledig gevulde buffer onderscheiden van een volledig lege?
Bij head == tail wordt meestal bepaald dat de buffer leeg is. Voor vol kan men ofwel één cel onbezet laten, of het aantal elementen in een expliciete teller bijhouden.
Kan de buffer worden gebruikt in een multithread-omgeving zonder sloten?
Nee, in de standaardcasus kunnen bij gelijktijdig lezen en schrijven races optreden. Men moet ofwel atomische operaties gebruiken, of sloten.
Wat gebeurt er als men de overschrijding van head of tail niet controleert?
In het geval van overschrijding zal dit leiden tot het overschrijden van de arraylimiet, wat resulteert in undefined behavior en mogelijke geheugenbeschadiging.
Een ontwikkelaar implementeerde een ringbuffer waarbij head == tail werd geïnterpreteerd als "leeg" en "vol" tegelijkertijd, waardoor het signaal van overschrijding verloren ging.
Voordelen:
Nadelen:
In plaats daarvan werd een elemententeller of een gereserveerde slot toegevoegd, zodat head nooit volledig tail achterhaalde.
Voordelen:
Nadelen: