In some cases it can happen that ::join() is called from multiple
threads at the same time. Checking the ::joinable() flag is not
race-free and so is unreliable to make sure that only one other thread
attempts to join at any given time. Add a mutex and a state variable to
make sure only one thread attempts to join, and make any other threads
wait.
Change-Id: I02fd236a416b035c98642535f1521be4a3a63fd9
Request a thread shutdown in the dtor in case the thread is still
running. Prevents destruction of std::thread with an active thread.
Change-Id: I51c4a43cf8d6402f4a690add936c95c2f700129d
Provide a single place for a running thread to check if it ought to shut
down. Use it in AmThreadWatcher.
Change-Id: I206111b34e3c658f0c2ce55627274b463b1e98d5
Use a std::list instead of a std::queue so that we can use iterators,
which allows us to delete elements directly without having to rebuild a
new queue with every loop iteration. This eliminates the n_thread_queue
and the swap.
Eliminate the wait condition _run_cond. This is only woken up when a
thread is added, which we don't care about. We only care when a thread
finishes, and there is no condition for that.
Use a lock guard. With this we can make sure the lock is in a consistent
state in case of an exception. Still catch and report exceptions.
Remove stub methods.
Change-Id: I59903f6a03863e5c106631e3db8706109915c8fb
Use an atomic enum to track state: idle, running, stopping, or stopped.
Use atomic compare and exchange to ensure consistency without requiring
a mutex.
Never detach threads. Always require a join. This makes for an easy and
reliable way to wait for a thread to finish.
Provide a default on_stop so that it can be omitted in child classes.
Change-Id: Id59942638b7f769090ac91c2049b7d934e876ffc
For the `AmThreadLocalStorage` its static `t` member
must be explicitely initialized outside of the template class.
Because it is a template class, it will only be instantiated
when used (when the data type is known), if no initialization
of the static member provided, then linker will fail to link
it (for other users like `RedisCheckpointWriter` which instantiates
`AmThreadLocalStorage` with `RedisConnection`).
Fixes:
ERROR: opening plugin '/usr/lib/sems-pbx/plug-in//redis_store.so':
/usr/lib/sems-pbx/plug-in//redis_store.so: undefined symbol: _ZN20AmThreadLocalStorageI15RedisConnectionE1tE
ERROR: while loading plug-in '/usr/lib/sems-pbx/plug-in//redis_store.so'
Change-Id: Iad3072c07fd04c5341838bb2a2c08858ca94b03a
Use std::condition_variable and std::mutex to implement AmCondition.
Only bools are used for conditions in the code, so make it not a
template.
Change-Id: I57d67492e29c220a5ce941ef67d142b34dcebbff
Re-implement AmMutex as a subclass of std::mutex. Provide copy and
assignment constructors so that it can be used as a member of another
class without preventing it from being copy/assignment constructed.
Change-Id: Id300a6501105a7871396c2be9380d6e0eae02cc7