Add Stoppable::alertable_sleep_for

This commit is contained in:
Vinnie Falco
2015-12-23 11:58:38 -05:00
parent 95dcdf7ddc
commit 3c6534dc91
2 changed files with 53 additions and 7 deletions
+45 -3
View File
@@ -22,10 +22,11 @@
#include <beast/intrusive/LockFreeStack.h>
#include <beast/utility/Journal.h>
#include <beast/threads/WaitableEvent.h>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
namespace beast {
@@ -189,6 +190,15 @@ public:
/** Returns `true` if all children have stopped. */
bool areChildrenStopped () const;
/** Sleep or wake up on stop.
@return `true` if we are stopping
*/
template <class Rep, class Period>
bool
alertable_sleep_for(
std::chrono::duration<Rep, Period> const& d);
protected:
/** Called by derived classes to indicate that the stoppable has stopped. */
void stopped ();
@@ -316,6 +326,15 @@ public:
*/
void stop (Journal j);
/** Sleep or wake up on stop.
@return `true` if we are stopping
*/
template <class Rep, class Period>
bool
alertable_sleep_for(
std::chrono::duration<Rep, Period> const& d);
private:
/* Notify a root stoppable and children to stop, without waiting.
Has no effect if the stoppable was already notified.
@@ -326,11 +345,34 @@ private:
void stopAsync(Journal j);
std::atomic<bool> m_prepared;
std::atomic<bool> m_calledStop;
bool m_calledStop;
std::atomic<bool> m_calledStopAsync;
std::mutex m_;
std::condition_variable c_;
};
/** @} */
//------------------------------------------------------------------------------
template <class Rep, class Period>
bool
RootStoppable::alertable_sleep_for(
std::chrono::duration<Rep, Period> const& d)
{
std::unique_lock<std::mutex> lock(m_);
if (m_calledStop)
return true;
return c_.wait_for(lock, d, [this]{return m_calledStop;});
}
template <class Rep, class Period>
bool
Stoppable::alertable_sleep_for(
std::chrono::duration<Rep, Period> const& d)
{
return m_root.alertable_sleep_for(d);
}
}
#endif
+8 -4
View File
@@ -183,12 +183,16 @@ void RootStoppable::stop (Journal j)
// Must have a prior call to start()
bassert (m_started);
if (m_calledStop.exchange (true) == true)
{
j.warning << "Stoppable::stop called again";
return;
std::lock_guard<std::mutex> lock(m_);
if (m_calledStop)
{
j.warning << "Stoppable::stop called again";
return;
}
m_calledStop = true;
c_.notify_all();
}
stopAsync (j);
stopRecursive (j);
}