added comments
This commit is contained in:
parent
70aad3fe1c
commit
b12ae5b0cb
5 changed files with 120 additions and 27 deletions
|
|
@ -1,16 +1,30 @@
|
|||
#pragma once
|
||||
#include <mutex>
|
||||
|
||||
/**
|
||||
* 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<std::mutex> lock(mtx);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schreibt einen neuen Wert
|
||||
* @param new_val Der neue Wert
|
||||
*/
|
||||
void write(int new_val) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
value = new_val;
|
||||
|
|
|
|||
17
main.cpp
17
main.cpp
|
|
@ -1,13 +1,26 @@
|
|||
#include "sensor_network.h"
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,61 @@
|
|||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
/**
|
||||
* 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 <size_t N>
|
||||
class RingBuffer {
|
||||
std::array<int, N> data;
|
||||
size_t read = 0;
|
||||
size_t write = 0;
|
||||
bool full = false;
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
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
|
||||
|
||||
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<std::mutex> 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<std::mutex> 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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,51 +3,77 @@
|
|||
#include <random>
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* Startet das Sensornetzwerk
|
||||
* @param sensors Anzahl der Sensor-Threads
|
||||
* @param analysers Anzahl der Analyse-Threads
|
||||
*/
|
||||
template <size_t N>
|
||||
void SensorNetwork<N>::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 <size_t N>
|
||||
void SensorNetwork<N>::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>;
|
||||
|
|
|
|||
|
|
@ -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 <size_t N>
|
||||
class SensorNetwork {
|
||||
RingBuffer<N> buffer;
|
||||
AnalysisModel model;
|
||||
std::atomic<bool> running = false;
|
||||
std::vector<std::thread> threads;
|
||||
RingBuffer<N> buffer; // Gemeinsamer Datenpuffer
|
||||
AnalysisModel model; // Geteiltes Analysemodell
|
||||
std::atomic<bool> running = false; // Steuerflag für Threads
|
||||
std::vector<std::thread> threads; // Alle Threads
|
||||
|
||||
public:
|
||||
~SensorNetwork() { if (running) stop(); }
|
||||
|
||||
void start(size_t sensors, size_t analysers);
|
||||
void stop();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue