BS_Praktikum4/ring_buffer.h

64 lines
2 KiB
C
Raw Normal View History

2025-06-03 00:50:08 +02:00
#pragma once
2025-06-03 01:25:44 +02:00
#include <array>
2025-06-03 00:50:08 +02:00
#include <mutex>
#include <condition_variable>
2025-06-03 01:40:44 +02:00
/**
* Thread-sicherer Ringpuffer mit fester Größe N
* Implementiert das Producer-Consumer-Pattern mit:
* - Mutex für exklusiven Zugriff
* - Condition Variable für blockierendes Lesen
* - Überschreibt älteste Daten bei vollem Puffer
*/
2025-06-03 00:50:08 +02:00
template <size_t N>
class RingBuffer {
2025-06-03 01:40:44 +02:00
std::array<int, N> data; // Speicher für die Elemente
size_t read = 0; // Lese-Position
size_t write = 0; // Schreib-Position
bool full = false; // Flag für vollen Puffer
std::mutex mtx; // Schützt alle Zugriffe
std::condition_variable cv; // Synchronisiert Leser
2025-06-03 00:50:08 +02:00
public:
2025-06-03 01:40:44 +02:00
/**
* Schreibt einen Wert in den Puffer
* @param value Der zu schreibende Wert
*
* Funktionsablauf:
* 1. Sperrt den Puffer mit Mutex
* 2. Schreibt Wert an aktueller Position
* 3. Überschreibt ältesten Wert wenn voll
* 4. Aktualisiert Schreib-Position
* 5. Benachrichtigt wartende Leser
*/
2025-06-03 00:50:08 +02:00
void push(int value) {
2025-06-03 01:25:44 +02:00
std::lock_guard<std::mutex> lock(mtx);
data[write] = value;
2025-06-03 01:40:44 +02:00
write = (write + 1) % N; // Ringverhalten
if (full) read = (read + 1) % N; // Überschreiben
full = (write == read); // Update Voll-Flag
cv.notify_one(); // Wecke einen Leser
2025-06-03 00:50:08 +02:00
}
2025-06-03 01:40:44 +02:00
/**
* Liest einen Wert aus dem Puffer (blockierend)
* @return Der gelesene Wert
*
* Funktionsablauf:
* 1. Sperrt den Puffer
* 2. Wartet bis Daten verfügbar
* 3. Liest Wert und aktualisiert Position
* 4. Gibt Wert zurück
*/
2025-06-03 00:50:08 +02:00
int pop() {
std::unique_lock<std::mutex> lock(mtx);
2025-06-03 01:40:44 +02:00
// Warte bis Daten da sind (verhindert Busy Waiting)
2025-06-03 01:25:44 +02:00
cv.wait(lock, [this]{ return full || write != read; });
int val = data[read];
2025-06-03 01:40:44 +02:00
read = (read + 1) % N; // Ringverhalten
full = false; // Nicht mehr voll
2025-06-03 01:25:44 +02:00
return val;
2025-06-03 00:50:08 +02:00
}
2025-06-03 01:25:44 +02:00
};