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
|
|
|
};
|