[asterisk-scf-commits] asterisk-scf/integration/util-cpp.git branch "route_replica" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Sat Apr 16 21:14:38 CDT 2011
branch "route_replica" has been updated
via d2ea2f1f04fd9ad34552d5c79f806d2b9bd952af (commit)
from 841b6f6da15190289390c5b4ba900793a497dc7f (commit)
Summary of changes:
.../AsteriskSCF/StateMachine/SimpleStateMachine.h | 108 ++++++++++++++++----
1 files changed, 87 insertions(+), 21 deletions(-)
- Log -----------------------------------------------------------------
commit d2ea2f1f04fd9ad34552d5c79f806d2b9bd952af
Author: Ken Hunt <ken.hunt at digium.com>
Date: Sat Apr 16 21:12:38 2011 -0500
Added thread safety for execute() operation.
diff --git a/StateMachine/include/AsteriskSCF/StateMachine/SimpleStateMachine.h b/StateMachine/include/AsteriskSCF/StateMachine/SimpleStateMachine.h
index 538c941..673c93b 100644
--- a/StateMachine/include/AsteriskSCF/StateMachine/SimpleStateMachine.h
+++ b/StateMachine/include/AsteriskSCF/StateMachine/SimpleStateMachine.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <map>
@@ -26,13 +27,12 @@ namespace StateMachine
{
/**
- * A simple state machine. User's provide a definition of the state type (probably an enum type) and
- * a type that can be executed using operator() to handle execution for a given state.
+ * A simple state machine. User's provide a definition of the enum type that defines the
+ * valid states.
* A listener interface is provided to allow monitoring state changes and state execution.
- * - typename S State type
- * - typename F An executable operation for state handler
+ * - typename S Enum type that identifies all valid states.
*/
-template<typename S, typename F>
+template<typename S>
class SimpleStateMachine
{
public:
@@ -40,7 +40,6 @@ public:
/**
* Listener interface for monitoring the state machine.
*/
-
class StateMachineListener
{
public:
@@ -48,21 +47,37 @@ public:
virtual void stateExecutionStart(S state) = 0;
virtual void stateExecutionComplete(S state) = 0;
virtual void stateTransition(S oldState, S newState) = 0;
+ virtual void shutdown() = 0;
protected:
StateMachineListener() {}
};
- //typedef StateMachineListener<S> StateMachineListenerType;
+ /**
+ * RAII setter for a boolean.
+ */
+ class ExecutionGuard
+ {
+ public:
+ ExecutionGuard(bool &val) : mGuard(val) {mGuard = true;}
+ ~ExecutionGuard() {mGuard = false;}
+
+ private:
+ bool &mGuard;
+ };
public:
/**
* Constructor.
* @param defaultState The default state for the state machine.
*/
- SimpleStateMachine(S defaultState)
+ SimpleStateMachine(S defaultState)
+ : mCurrentState(defaultState),
+ mNextState(defaultState),
+ mShutdown(false),
+ mInExecution(false)
+
{
- mCurrentState = mNextState = defaultState;
}
~SimpleStateMachine()
@@ -87,7 +102,7 @@ public:
/**
* Sets the execution handler for a given state.
*/
- void addState(S state, const F& handler)
+ void addState(S state, const boost::function<void ()>& handler)
{
mStates[state] = handler;
}
@@ -105,10 +120,14 @@ public:
*/
void execute()
{
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+ ExecutionGuard guard(mInExecution);
+
// Notify all listeners that execution is starting.
sendExecutionStartNotice(mCurrentState);
- std::map<S, F>::iterator it = mStates.find(mCurrentState);
+ std::map<S, boost::function<void ()> >::iterator it = mStates.find(mCurrentState);
if (it != mStates.end())
{
// Execute
@@ -125,8 +144,31 @@ public:
sendTransitionNotice(mCurrentState, mNextState);
mCurrentState = mNextState;
}
+
+ if (mShutdown)
+ {
+ // Send shutdown notice to the listeners.
+ sendShutdownNotice();
+ }
}
+ /**
+ * Shutdown the state machine.
+ */
+ void shutdown()
+ {
+ // If we being called as a result of state execution (as expected),
+ // mark the state machine for shutdown, and let execution() handle it.
+ if (mInExecution)
+ {
+ mShutdown = true;
+ }
+ else
+ {
+ // Send shutdown notice to the listeners.
+ sendShutdownNotice();
+ }
+ }
private:
@@ -146,9 +188,6 @@ private:
{
x->stateExecutionStart(mState);
}
- catch(const Ice::Exception&)
- {
- }
catch(...)
{
}
@@ -181,9 +220,6 @@ private:
{
x->stateExecutionComplete(mState);
}
- catch(const Ice::Exception&)
- {
- }
catch(...)
{
}
@@ -215,9 +251,6 @@ private:
{
x->stateTransition(mOldState, mNewState);
}
- catch(const Ice::Exception&)
- {
- }
catch(...)
{
}
@@ -234,11 +267,44 @@ private:
std::for_each(mListeners.begin(), mListeners.end(), TransitionNotice<S> (oldState, newState));
}
+ /**
+ * Functor for forwarding shutdown() notices.
+ */
+ template<typename S>
+ class ShutdownNotice
+ {
+ // Types: S - State
+ public:
+ ShutdownNotice() {}
+ ~ShutdownNotice() {}
+ void operator() (boost::shared_ptr<StateMachineListener >& x)
+ {
+ try
+ {
+ x->shutdown();
+ }
+ catch(...)
+ {
+ }
+ }
+ };
+
+ /**
+ * Forward the state transition notice to all registered listeners.
+ */
+ void sendShutdownNotice()
+ {
+ std::for_each(mListeners.begin(), mListeners.end(), ShutdownNotice<S> ());
+ }
+
/// Class state
- std::map<S, F> mStates;
+ std::map<S, boost::function<void ()> > mStates;
S mCurrentState;
S mNextState;
+ bool mShutdown;
+ bool mInExecution;
+ boost::shared_mutex mLock;
std::vector<boost::shared_ptr<StateMachineListener > > mListeners;
};
-----------------------------------------------------------------------
--
asterisk-scf/integration/util-cpp.git
More information about the asterisk-scf-commits
mailing list