36 template <
class t_Arg,
class... t_Args>
37 void log(
const t_Arg &arg, t_Args &&...args)
const
41 log(std::forward<t_Args>(args)...);
46 std::cerr << std::endl;
81 explicit Restart(
const std::size_t attempts = 0,
const std::size_t sleep_ms = 0)
92 [[nodiscard]]
bool isOk(
const std::size_t attempt)
const
104 std::this_thread::sleep_for(std::chrono::milliseconds(
sleep_ms_));
119 const int priority = 0,
120 const int policy = SCHED_FIFO,
121 const bool ignore_failures =
true)
129 bool apply(
const std::thread::native_handle_type &&handle)
const
133 sched_param sched_params;
136 if (0 != pthread_setschedparam(handle,
policy_, &sched_params))
150 #ifdef THREAD_SUPERVISOR_THOU_SHALT_NOT_PASS
160 template <
class... t_Args>
167 template <
class... t_Args>
174 template <
class... t_Args>
181 template <
class... t_Args>
193 template <
class t_Logger = log::StdErr>
203 using List = std::list<Thread>;
213 template <
class t_Logger,
class t_Function,
class... t_Args>
219 std::bind(
function, std::forward<t_Args>(args)...)();
225 std::bind(
function, std::forward<t_Args>(args)...)();
227 catch (
const std::exception &e)
229 supervisor->log(
"Supervisor / intercepted thread exception: ", e.what());
234 supervisor->log(
"Supervisor error: unknown exception handling type");
240 template <
class t_Logger,
class t_Function,
class... t_Args>
243 bool started =
false;
256 "Supervisor / restarting thread: ",
266 startOnce(supervisor,
function, std::forward<t_Args>(args)...);
271 template <
class t_Logger,
class t_Function,
class... t_Args>
276 startLoop(supervisor,
function, std::forward<t_Args>(args)...);
280 startOnce(supervisor,
function, std::forward<t_Args>(args)...);
296 supervisor->log(
"Supervisor error: unknown termination handling type");
303 template <
class t_Logger,
class... t_Args>
313 &Thread::startThread<t_Logger, t_Args...>,
this, supervisor, std::forward<t_Args>(args)...);
317 supervisor->log(
"Supervisor error: could not configure custom thread scheduling.");
337 template <
class t_Logger>
345 std::atomic<bool> interrupted_;
355 bool wait(
const std::size_t wait_ms)
357 const std::size_t sleep_ms = 10;
361 std::size_t counter = 0;
364 if (counter * sleep_ms < wait_ms)
379 std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
390 log(
"Threads did not terminate in the given time after request.");
405 void drop(
const std::list<Thread>::iterator &item)
418 interrupted_ =
false;
431 log(
"Destructor of Supervisor is reached with 'interrupted_ = false',"
432 "which means that terminate() method was not called.");
439 log(
"Destructor of Supervisor is reached with some threads still running.");
455 return (interrupted_);
460 bool stop(
const std::size_t wait_ms = 10000)
463 return (
wait(wait_ms));
468 template <
class... t_Args>
469 void add(t_Args &&...args)
474 log(
"Addition of a thread attempted after interrupt.");
481 threads_.back().start(
this, --
threads_.end(), std::forward<t_Args>(args)...);
489 template <
class t_Logger = log::StdErr>
521 template <
class... t_Args>
void log(const t_Arg &arg, t_Args &&...args) const
Inheritable supervisor simplifies starting class methods in separate threads.
Supervisor< t_Logger > thread_supervisor_
bool isThreadSupervisorInterrupted() const
Should be checked by threaded class methods.
Supervisor< t_Logger > & getThreadSupervisor()
const Supervisor< t_Logger > & getThreadSupervisor() const
~InheritableSupervisor()=default
void addSupervisedThread(t_Args &&...args)
Add a thread: (<thread parameters>, <function pointer>, <this>, <function parameters>)
virtual void stopSupervisedThreads()=0
Restart(const std::size_t attempts=0, const std::size_t sleep_ms=0)
delay between attempts
bool isOk(const std::size_t attempt) const
std::size_t sleep_ms_
0 = unlimited
Scheduling parameters, POSIX threads only, see pthread_setschedparam.
Scheduling(const int priority=0, const int policy=SCHED_FIFO, const bool ignore_failures=true)
proceed if scheduling parameters could not be set
bool ignore_failures_
thread policy
int policy_
thread priority
bool apply(const std::thread::native_handle_type &&handle) const
ExceptionPolicy exception_policy_
TerminationPolicy termination_policy_
do not allow threads to exit / crash quietly
Parameters(const ExceptionPolicy exception_policy, t_Args &&...args)
Parameters(const Restart &&restart, t_Args &&...args)
ExceptionPolicy
Exception handling policy.
Parameters(const TerminationPolicy termination_policy, t_Args &&...args)
TerminationPolicy
What to do when thread terminated.
@ KILLALL
ignore and proceed
Parameters(const Scheduling &&scheduling, t_Args &&...args)
THREAD_SUPERVISOR_DISABLE_CLASS_COPY(Supervisor) protected std::mutex threads_mutex_
std::mutex terminated_threads_mutex_
bool isInterrupted() const
Check if interrupted, child threads should stop when true (pass supervisor as a parameter).
std::list< Thread::Reference > terminated_threads_
void interrupt()
Interrupt execution, see isInterrupted.
bool wait(const std::size_t wait_ms)
bool stop(const std::size_t wait_ms=10000)
Interrupt and wait for children to stop.
void drop(const std::list< Thread >::iterator &item)
void add(t_Args &&...args)
Add a thread: (<thread parameters>, <function pointer>, <function parameters>)
void startLoop(Supervisor< t_Logger > *supervisor, t_Function &&function, t_Args &&...args)
void startThread(Supervisor< t_Logger > *supervisor, t_Function &&function, t_Args &&...args)
void start(Supervisor< t_Logger > *supervisor, Reference self, const Parameters &¶meters, t_Args &&...args)
void startOnce(Supervisor< t_Logger > *supervisor, t_Function &&function, t_Args &&...args)
#define THREAD_SUPERVISOR_DISABLE_CLASS_COPY(Class)
Class definitions that prevent copying.