diff --git a/analysis_model.h b/analysis_model.h index e17e11b..e775eb5 100644 --- a/analysis_model.h +++ b/analysis_model.h @@ -1,16 +1,30 @@ #pragma once #include +/** + * Thread-sicheres Analysemodell + * Vereinfachte Implementierung mit: + * - Einfachem Mutex-Schutz (kein Reader-Writer-Lock) + * - Für seltene Schreibzugriffe geeignet + */ class AnalysisModel { - int value = 0; - std::mutex mtx; + int value = 0; // Der gespeicherte Wert + std::mutex mtx; // Schützt Lese/Schreibzugriffe public: + /** + * Liest den aktuellen Wert + * @return Der gespeicherte Wert + */ int read() { std::lock_guard lock(mtx); return value; } + /** + * Schreibt einen neuen Wert + * @param new_val Der neue Wert + */ void write(int new_val) { std::lock_guard lock(mtx); value = new_val; diff --git a/main.cpp b/main.cpp index d13d9c2..0b81389 100644 --- a/main.cpp +++ b/main.cpp @@ -1,13 +1,26 @@ #include "sensor_network.h" #include +/** + * Hauptprogramm + * Startet die Simulation mit festen Parametern + * (Könnte leicht für interaktive Eingabe erweitert werden) + */ int main() { + // Netzwerk mit Puffergröße 8 erstellen SensorNetwork<8> network; - std::cout << "Starting simulation...\n"; - network.start(2, 2); // 2 sensors, 2 analysers + std::cout << "Starting simulation...\n"; + + // 2 Sensoren und 2 Analyse-Module starten + network.start(2, 2); + + // 30 Sekunden laufen lassen std::this_thread::sleep_for(std::chrono::seconds(30)); + + // Netzwerk stoppen network.stop(); + std::cout << "Simulation finished\n"; return 0; } diff --git a/ring_buffer.h b/ring_buffer.h index 4e7a0ff..bb7b34c 100644 --- a/ring_buffer.h +++ b/ring_buffer.h @@ -3,31 +3,61 @@ #include #include +/** + * 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 + */ template class RingBuffer { - std::array data; - size_t read = 0; - size_t write = 0; - bool full = false; - std::mutex mtx; - std::condition_variable cv; + std::array 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 public: + /** + * 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 + */ void push(int value) { std::lock_guard lock(mtx); data[write] = value; - write = (write + 1) % N; - if (full) read = (read + 1) % N; - full = (write == read); - cv.notify_one(); + write = (write + 1) % N; // Ringverhalten + if (full) read = (read + 1) % N; // Überschreiben + full = (write == read); // Update Voll-Flag + cv.notify_one(); // Wecke einen Leser } + /** + * 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 + */ int pop() { std::unique_lock lock(mtx); + // Warte bis Daten da sind (verhindert Busy Waiting) cv.wait(lock, [this]{ return full || write != read; }); int val = data[read]; - read = (read + 1) % N; - full = false; + read = (read + 1) % N; // Ringverhalten + full = false; // Nicht mehr voll return val; } }; diff --git a/sensor_network.cpp b/sensor_network.cpp index ddf33a4..bd8c6fd 100644 --- a/sensor_network.cpp +++ b/sensor_network.cpp @@ -3,51 +3,77 @@ #include #include +/** + * Startet das Sensornetzwerk + * @param sensors Anzahl der Sensor-Threads + * @param analysers Anzahl der Analyse-Threads + */ template void SensorNetwork::start(size_t sensors, size_t analysers) { running = true; - // Sensor threads + // Sensor-Threads erstellen for (size_t i = 0; i < sensors; ++i) { threads.emplace_back([this] { std::mt19937 gen(std::random_device{}()); std::uniform_int_distribution<> dist(0, 100); + while (running) { - std::this_thread::sleep_for(std::chrono::milliseconds(100 + gen() % 400)); + // Zufälliges Intervall (100-500ms) + std::this_thread::sleep_for( + std::chrono::milliseconds(100 + gen() % 400)); + + // Messwert generieren und speichern buffer.push(dist(gen)); } }); } - // Analyser threads + // Analyse-Threads erstellen for (size_t i = 0; i < analysers; ++i) { threads.emplace_back([this] { while (running) { + // Daten aus Puffer lesen int data = buffer.pop(); + + // Analysemodell lesen int model_val = model.read(); - std::cout << "Data: " << data << " Model: " << model_val << "\n"; + + // Ausgabe (könnte auch analysieren) + std::cout << "Data: " << data + << " Model: " << model_val << "\n"; } }); } - // Controller thread + // Controller-Thread erstellen threads.emplace_back([this] { std::mt19937 gen(std::random_device{}()); while (running) { - std::this_thread::sleep_for(std::chrono::milliseconds(500 + gen() % 1500)); + // Zufälliges Update-Intervall (500-2000ms) + std::this_thread::sleep_for( + std::chrono::milliseconds(500 + gen() % 1500)); + + // Analysemodell aktualisieren model.write(gen() % 100); } }); } +/** + * Stoppt das Sensornetzwerk und wartet auf Threads + */ template void SensorNetwork::stop() { - running = false; + running = false; // Signal zum Stoppen + + // Auf alle Threads warten for (auto& t : threads) { if (t.joinable()) t.join(); } } +// Explizite Instanziierungen für gängige Puffergrößen template class SensorNetwork<8>; template class SensorNetwork<16>; template class SensorNetwork<32>; diff --git a/sensor_network.h b/sensor_network.h index 148f2fa..af314c2 100644 --- a/sensor_network.h +++ b/sensor_network.h @@ -5,15 +5,25 @@ #include "ring_buffer.h" #include "analysis_model.h" +/** + * Hauptklasse für das Sensornetzwerk + * @tparam N Größe des Ringpuffers + * + * Verwaltet alle Komponenten: + * - Ringpuffer für Sensordaten + * - Analysemodell + * - Threads für Sensoren, Analyse und Controller + */ template class SensorNetwork { - RingBuffer buffer; - AnalysisModel model; - std::atomic running = false; - std::vector threads; + RingBuffer buffer; // Gemeinsamer Datenpuffer + AnalysisModel model; // Geteiltes Analysemodell + std::atomic running = false; // Steuerflag für Threads + std::vector threads; // Alle Threads public: ~SensorNetwork() { if (running) stop(); } + void start(size_t sensors, size_t analysers); void stop(); };