| 117 | |
| 118 | private: |
| 119 | void producerLoop() { |
| 120 | // Thread-local RNG — each thread gets its own engine (no data race) |
| 121 | std::mt19937 rng(std::random_device{}()); |
| 122 | std::uniform_real_distribution<double> noise(0.0, 0.1); |
| 123 | |
| 124 | while (running_) { |
| 125 | IMUReading reading{}; |
| 126 | reading.timestamp = std::chrono::steady_clock::now(); |
| 127 | reading.accel_z = -9.81 + noise(rng); |
| 128 | |
| 129 | if (!queue_.push(reading)) break; |
| 130 | std::this_thread::sleep_for(config::IMU_PERIOD); |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | void consumerLoop() { |
| 135 | // Rely solely on pop()'s internal lock + shutdown signal, |