Refactor Stoppable:

The Stoppable interface aids in the enforcement of invariants needed to
successful start and stop a multi-threaded application composed of classes
that depend on each other in complex ways.
* Test written to confirm the current behavior.
* Comments updated to reflect the current behavior.
* Public API reduced to what is currently in use.
* Protected data members made private.
* volatile bool members changed to std::atomic<bool>.
* std::atomic<int> members changed to std::atomic<bool>.
* Name storage uses std::string
This commit is contained in:
Howard Hinnant
2014-10-29 14:23:41 -04:00
committed by Vinnie Falco
parent 68fe1a7c8f
commit eb64a4387d
4 changed files with 481 additions and 31 deletions

View File

@@ -25,7 +25,7 @@ Stoppable::Stoppable (char const* name, RootStoppable& root)
: m_name (name)
, m_root (root)
, m_child (this)
, m_started (0)
, m_started (false)
, m_stopped (false)
, m_childrenStopped (false)
{
@@ -35,7 +35,7 @@ Stoppable::Stoppable (char const* name, Stoppable& parent)
: m_name (name)
, m_root (parent.m_root)
, m_child (this)
, m_started (0)
, m_started (false)
, m_stopped (false)
, m_childrenStopped (false)
{
@@ -48,7 +48,7 @@ Stoppable::Stoppable (char const* name, Stoppable& parent)
Stoppable::~Stoppable ()
{
// Children must be stopped.
bassert (m_started.load () == 0 || m_childrenStopped);
bassert (!m_started || m_childrenStopped);
}
bool Stoppable::isStopping() const
@@ -124,7 +124,6 @@ void Stoppable::stopRecursive (Journal journal)
// if we get here then all children have stopped
//
memoryBarrier ();
m_childrenStopped = true;
onChildrenStopped ();
@@ -145,39 +144,39 @@ void Stoppable::stopRecursive (Journal journal)
RootStoppable::RootStoppable (char const* name)
: Stoppable (name, *this)
, m_prepared (0)
, m_calledStop (0)
, m_calledStopAsync (0)
, m_prepared (false)
, m_calledStop (false)
, m_calledStopAsync (false)
{
}
bool RootStoppable::isStopping() const
{
return m_calledStopAsync.load () != 0;
return m_calledStopAsync;
}
void RootStoppable::prepare ()
{
if (m_prepared.exchange (1) == 0)
if (m_prepared.exchange (true) == false)
prepareRecursive ();
}
void RootStoppable::start ()
{
// Courtesy call to prepare.
if (m_prepared.exchange (1) == 0)
if (m_prepared.exchange (true) == false)
prepareRecursive ();
if (m_started.exchange (1) == 0)
if (m_started.exchange (true) == false)
startRecursive ();
}
void RootStoppable::stop (Journal journal)
{
// Must have a prior call to start()
bassert (m_started.load () != 0);
bassert (m_started);
if (m_calledStop.exchange (1) == 1)
if (m_calledStop.exchange (true) == true)
{
journal.warning << "Stoppable::stop called again";
return;
@@ -189,7 +188,7 @@ void RootStoppable::stop (Journal journal)
void RootStoppable::stopAsync ()
{
if (m_calledStopAsync.exchange (1) == 0)
if (m_calledStopAsync.exchange (true) == false)
stopAsyncRecursive ();
}