diff --git a/beast/threads/Stoppable.h b/beast/threads/Stoppable.h index 637b078c0..9ff21dcb5 100644 --- a/beast/threads/Stoppable.h +++ b/beast/threads/Stoppable.h @@ -265,6 +265,7 @@ protected: char const* m_name; RootStoppable& m_root; Child m_child; + Atomic m_started; bool volatile m_stopped; bool volatile m_childrenStopped; Children m_children; @@ -301,6 +302,8 @@ public: /** Notify a root stoppable and children to stop, and block until stopped. Has no effect if the stoppable was already notified. This blocks until the stoppable and all of its children have stopped. + Undefined behavior results if stop() is called without a previous call + to start(). Thread safety: Safe to call from any thread not associated with a Stoppable. */ @@ -316,7 +319,6 @@ public: private: Atomic m_prepared; - Atomic m_started; Atomic m_calledStop; Atomic m_calledStopAsync; }; diff --git a/beast/threads/impl/Stoppable.cpp b/beast/threads/impl/Stoppable.cpp index 75e01986a..35eb60df6 100644 --- a/beast/threads/impl/Stoppable.cpp +++ b/beast/threads/impl/Stoppable.cpp @@ -46,7 +46,7 @@ Stoppable::Stoppable (char const* name, Stoppable& parent) Stoppable::~Stoppable () { // Children must be stopped. - bassert (m_childrenStopped); + bassert (m_started.get() == 0 || m_childrenStopped); } bool Stoppable::isStopping() const @@ -177,6 +177,9 @@ void RootStoppable::start () void RootStoppable::stop (Journal journal) { + // Must have a prior call to start() + bassert (m_started.get() != 0); + if (! m_calledStop.compareAndSetBool (1, 0)) { journal.warning << "Stoppable::stop called again";