#pragma once #include #include #include #include /** * Thread-sicherer Ringpuffer mit fester Größe * @tparam N Größe des Puffers (muss > 1 sein) * * Implementiert das Producer-Consumer Pattern mit: * - Mutex für exklusiven Zugriff * - Condition Variable für blockierendes Pop * - Überschreibt älteste Daten bei vollem Puffer */ template class RingBuffer { static_assert(N > 1, "Buffer size must be greater than 1"); private: std::vector data; // Speicher für Elemente size_t read_ptr = 0; // Lesezeiger (nächstes zu lesendes Element) size_t write_ptr = 0; // Schreibzeiger (nächstes freie Position) bool full = false; // Flag, ob Puffer voll ist // Synchronisationsprimitive std::mutex mtx; // Schützt alle internen Zustände std::condition_variable not_empty; // Signalisiert, dass Daten verfügbar sind // Hilfsfunktion: Zeiger mit Ringverhalten bewegen size_t advance(size_t ptr) const { return (ptr + 1) % N; } public: RingBuffer() : data(N, 0) {} /** * Schreibt Wert in den Puffer * @param value Der zu schreibende Wert * * Funktionsweise: * 1. Sperrt Mutex für exklusiven Zugriff * 2. Schreibt Wert an aktueller write_ptr * 3. Bei vollem Puffer: Bewegt read_ptr (überschreibt ältesten Wert) * 4. Aktualisiert write_ptr und full-Flag * 5. Benachrichtigt einen wartenden Consumer */ void push(int value) { std::unique_lock lock(mtx); // Schreibe Wert data[write_ptr] = value; // Überschreibe ältesten Wert bei vollem Puffer if(full) { read_ptr = advance(read_ptr); } // Zeiger aktualisieren write_ptr = advance(write_ptr); full = (write_ptr == read_ptr); // Benachrichtige einen wartenden Consumer not_empty.notify_one(); } /** * Liest Wert aus dem Puffer (blockierend) * @return Der gelesene Wert * * Funktionsweise: * 1. Sperrt Mutex * 2. Wartet mit Condition Variable bis Daten verfügbar * 3. Liest Wert an read_ptr * 4. Aktualisiert read_ptr und full-Flag * 5. Gibt Wert zurück */ int pop() { std::unique_lock lock(mtx); // Warte bis Daten verfügbar (verhindert Busy Waiting) not_empty.wait(lock, [this]() { return !is_empty(); }); // Lese und aktualisiere Zustand int value = data[read_ptr]; read_ptr = advance(read_ptr); full = false; return value; } // Prüft ob Puffer leer ist bool is_empty() const { return !full && (read_ptr == write_ptr); } // Prüft ob Puffer voll ist bool is_full() const { return full; } };