ILLIXR: Illinois Extended Reality Testbed
managed_thread.hpp
1 #pragma once
2 
3 #include <atomic>
4 #include <cassert>
5 #include <functional>
6 #include <stdexcept>
7 #include <thread>
8 #include <utility>
9 
10 namespace ILLIXR {
11 
16 private:
17  std::atomic<bool> _m_stop{false};
18  std::thread _m_thread;
19  std::function<void()> _m_body;
20  std::function<void()> _m_on_start;
21  std::function<void()> _m_on_stop;
22 
23  void thread_main() {
24  assert(_m_body);
25  if (_m_on_start) {
26  _m_on_start();
27  }
28  while (!this->_m_stop.load()) {
29  _m_body();
30  }
31  if (_m_on_stop) {
32  _m_on_stop();
33  }
34  }
35 
36 public:
40  managed_thread() noexcept = default;
41 
49  explicit managed_thread(std::function<void()> body, std::function<void()> on_start = std::function<void()>{},
50  std::function<void()> on_stop = std::function<void()>{}) noexcept
51  : _m_body{std::move(body)}
52  , _m_on_start{std::move(on_start)}
53  , _m_on_stop{std::move(on_stop)} { }
54 
58  ~managed_thread() noexcept {
59  if (get_state() == state::running) {
60  stop();
61  }
62  assert(get_state() == state::stopped || get_state() == state::startable || get_state() == state::nonstartable);
63  // assert(!_m_thread.joinable());
64  }
65 
67  enum class state {
68  nonstartable,
69  startable,
70  running,
71  stopped,
72  };
73 
76  state get_state() {
77  bool stopped = _m_stop.load();
78  if (!_m_body) {
79  return state::nonstartable;
80  } else if (!stopped && !_m_thread.joinable()) {
81  return state::startable;
82  } else if (!stopped && _m_thread.joinable()) {
83  return state::running;
84  } else if (stopped) {
85  return state::stopped;
86  } else {
87  throw std::logic_error{"Unknown state"};
88  }
89  }
90 
94  void start() {
95  assert(get_state() == state::startable);
96  _m_thread = std::thread{&managed_thread::thread_main, this};
97  assert(get_state() == state::running);
98  }
99 
103  void stop() {
104  assert(get_state() == state::running);
105  _m_stop.store(true);
106  _m_thread.join();
107  assert(get_state() == state::stopped);
108  }
109 };
110 
111 } // namespace ILLIXR
An object that manages a std::thread; it joins and exits when the object gets destructed.
Definition: managed_thread.hpp:15
~managed_thread() noexcept
Stops a thread, if necessary.
Definition: managed_thread.hpp:58
managed_thread() noexcept=default
Constructs a non-startable thread.
void start()
Moves a managed_thread from startable to running.
Definition: managed_thread.hpp:94
state
Possible states for a managed_thread.
Definition: managed_thread.hpp:67
void stop()
Moves a managed_thread from running to stopped.
Definition: managed_thread.hpp:103
RAC_ERRNO_MSG.
Definition: data_format.hpp:15