mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
202 lines
4.6 KiB
C++
202 lines
4.6 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#include "../Stoppable.h"
|
|
|
|
namespace beast {
|
|
|
|
Stoppable::Stoppable (char const* name, RootStoppable& root)
|
|
: m_name (name)
|
|
, m_root (root)
|
|
, m_child (this)
|
|
, m_stopped (false)
|
|
, m_childrenStopped (false)
|
|
{
|
|
}
|
|
|
|
Stoppable::Stoppable (char const* name, Stoppable& parent)
|
|
: m_name (name)
|
|
, m_root (parent.m_root)
|
|
, m_child (this)
|
|
, m_stopped (false)
|
|
, m_childrenStopped (false)
|
|
{
|
|
// Must not have stopping parent.
|
|
bassert (! parent.isStopping());
|
|
|
|
parent.m_children.push_front (&m_child);
|
|
}
|
|
|
|
Stoppable::~Stoppable ()
|
|
{
|
|
// Children must be stopped.
|
|
bassert (m_started.get() == 0 || m_childrenStopped);
|
|
}
|
|
|
|
bool Stoppable::isStopping() const
|
|
{
|
|
return m_root.isStopping();
|
|
}
|
|
|
|
bool Stoppable::isStopped () const
|
|
{
|
|
return m_stopped;
|
|
}
|
|
|
|
bool Stoppable::areChildrenStopped () const
|
|
{
|
|
return m_childrenStopped;
|
|
}
|
|
|
|
void Stoppable::stopped ()
|
|
{
|
|
m_stoppedEvent.signal();
|
|
}
|
|
|
|
void Stoppable::onPrepare ()
|
|
{
|
|
}
|
|
|
|
void Stoppable::onStart ()
|
|
{
|
|
}
|
|
|
|
void Stoppable::onStop ()
|
|
{
|
|
stopped();
|
|
}
|
|
|
|
void Stoppable::onChildrenStopped ()
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void Stoppable::prepareRecursive ()
|
|
{
|
|
for (Children::const_iterator iter (m_children.cbegin ());
|
|
iter != m_children.cend(); ++iter)
|
|
iter->stoppable->prepareRecursive ();
|
|
onPrepare ();
|
|
}
|
|
|
|
void Stoppable::startRecursive ()
|
|
{
|
|
onStart ();
|
|
for (Children::const_iterator iter (m_children.cbegin ());
|
|
iter != m_children.cend(); ++iter)
|
|
iter->stoppable->startRecursive ();
|
|
}
|
|
|
|
void Stoppable::stopAsyncRecursive ()
|
|
{
|
|
onStop ();
|
|
for (Children::const_iterator iter (m_children.cbegin ());
|
|
iter != m_children.cend(); ++iter)
|
|
iter->stoppable->stopAsyncRecursive ();
|
|
}
|
|
|
|
void Stoppable::stopRecursive (Journal journal)
|
|
{
|
|
// Block on each child from the bottom of the tree up.
|
|
//
|
|
for (Children::const_iterator iter (m_children.cbegin ());
|
|
iter != m_children.cend(); ++iter)
|
|
iter->stoppable->stopRecursive (journal);
|
|
|
|
// if we get here then all children have stopped
|
|
//
|
|
memoryBarrier ();
|
|
m_childrenStopped = true;
|
|
onChildrenStopped ();
|
|
|
|
// Now block on this Stoppable.
|
|
//
|
|
bool const timedOut (! m_stoppedEvent.wait (1 * 1000)); // milliseconds
|
|
if (timedOut)
|
|
{
|
|
journal.warning << "Waiting for '" << m_name << "' to stop";
|
|
m_stoppedEvent.wait ();
|
|
}
|
|
|
|
// once we get here, we know the stoppable has stopped.
|
|
m_stopped = true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
RootStoppable::RootStoppable (char const* name)
|
|
: Stoppable (name, *this)
|
|
{
|
|
}
|
|
|
|
RootStoppable::~RootStoppable ()
|
|
{
|
|
}
|
|
|
|
bool RootStoppable::isStopping() const
|
|
{
|
|
return m_calledStopAsync.get() != 0;
|
|
}
|
|
|
|
void RootStoppable::prepare ()
|
|
{
|
|
if (! m_prepared.compareAndSetBool (1, 0))
|
|
return;
|
|
|
|
prepareRecursive ();
|
|
}
|
|
|
|
void RootStoppable::start ()
|
|
{
|
|
// Courtesy call to prepare.
|
|
if (m_prepared.compareAndSetBool (1, 0))
|
|
prepareRecursive ();
|
|
|
|
if (! m_started.compareAndSetBool (1, 0))
|
|
return;
|
|
|
|
startRecursive ();
|
|
}
|
|
|
|
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";
|
|
return;
|
|
}
|
|
|
|
stopAsync ();
|
|
stopRecursive (journal);
|
|
}
|
|
|
|
void RootStoppable::stopAsync ()
|
|
{
|
|
if (! m_calledStopAsync.compareAndSetBool (1, 0))
|
|
return;
|
|
|
|
stopAsyncRecursive ();
|
|
}
|
|
|
|
}
|