| 121 | } |
| 122 | |
| 123 | void FileLogger2::writerLoop() |
| 124 | { |
| 125 | // local buffer in this thread |
| 126 | std::deque<Transition> transitions; |
| 127 | |
| 128 | // Signal readiness while holding the lock (establishes happens-before with constructor) |
| 129 | { |
| 130 | std::scoped_lock lock(_p->queue_mutex); |
| 131 | _p->writer_ready.store(true, std::memory_order_release); |
| 132 | } |
| 133 | _p->queue_cv.notify_one(); |
| 134 | |
| 135 | while(_p->loop) |
| 136 | { |
| 137 | transitions.clear(); |
| 138 | { |
| 139 | std::unique_lock lock(_p->queue_mutex); |
| 140 | _p->queue_cv.wait_for(lock, std::chrono::milliseconds(10), [this]() { |
| 141 | return !_p->transitions_queue.empty() || !_p->loop; |
| 142 | }); |
| 143 | // simple way to pop all the transitions from _p->transitions_queue into transitions |
| 144 | std::swap(transitions, _p->transitions_queue); |
| 145 | } |
| 146 | { |
| 147 | const std::scoped_lock file_lock(_p->file_mutex); |
| 148 | while(!transitions.empty()) |
| 149 | { |
| 150 | const auto trans = transitions.front(); |
| 151 | std::array<char, 9> write_buffer{}; |
| 152 | std::memcpy(write_buffer.data(), &trans.timestamp_usec, 6); |
| 153 | std::memcpy(write_buffer.data() + 6, &trans.node_uid, 2); |
| 154 | std::memcpy(write_buffer.data() + 8, &trans.status, 1); |
| 155 | |
| 156 | _p->file_stream.write(write_buffer.data(), 9); |
| 157 | transitions.pop_front(); |
| 158 | } |
| 159 | _p->file_stream.flush(); |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | } // namespace BT |