summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/asyncStore/jrnl2/State.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/qpid/asyncStore/jrnl2/State.h')
-rw-r--r--cpp/src/qpid/asyncStore/jrnl2/State.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/cpp/src/qpid/asyncStore/jrnl2/State.h b/cpp/src/qpid/asyncStore/jrnl2/State.h
new file mode 100644
index 0000000000..3a4354760a
--- /dev/null
+++ b/cpp/src/qpid/asyncStore/jrnl2/State.h
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * \file State.h
+ */
+
+#ifndef qpid_asyncStore_jrnl2_State_h_
+#define qpid_asyncStore_jrnl2_State_h_
+
+#include "Streamable.h"
+
+namespace qpid {
+namespace asyncStore {
+namespace jrnl2 {
+
+/**
+ * \brief Utility class to manage a simple state machine defined by an enumeration \a E.
+ *
+ * It is necessary that enumeration E has its default / initial value coded as value 0. This enumeration would
+ * be typically coded as follows:
+ * \code
+ * typedef enum {STATE1=0, STATE2, STATE3} myStates_t;
+ * class myStateMachine : State<myStates_t> {
+ * protected:
+ * void set(myStates_t s) { ... } // Implement state machine logic and transition checking here
+ * public:
+ * // State transition verbs
+ * void action1() { set(STATE2); }
+ * void action2() { set(STATE3); }
+ * };
+ * \endcode
+ *
+ * For child classes, the state machine transition logic is implemented in set(const E), and the state change
+ * verbs are implemented by calling set() with values from E. A call to reset() will return the state to the
+ * state numerically equal to 0, irrespective of the current state or state transition logic.
+ *
+ * Function getAsStr() returns the current state as a string, and is usually implemented by calling a local static
+ * function which translates the values of E into c-string literals.
+ */
+template <class E> class State : public Streamable {
+public:
+ /**
+ * \brief Default constructor, which sets the internal state m_state to the state in E which is numerically
+ * equal to 0.
+ */
+ State<E>() :
+ Streamable(),
+ m_state(E(0))
+ {}
+
+ /**
+ * \brief Constructor which sets the internal state m_state to the value \a s.
+ */
+ State<E>(const E s) :
+ Streamable(),
+ m_state(s)
+ {}
+
+ /**
+ * \brief Copy constructor, which sets the internal state m_state to the same value as that of the copied
+ * instance \a s.
+ */
+ State<E>(const State<E>& s) :
+ Streamable(),
+ m_state(s.m_state)
+ {}
+
+ /**
+ * \brief Virtual destructor
+ */
+ virtual ~State()
+ {}
+
+ /**
+ * \brief Get the internal state m_state as an enumeration of type E.
+ *
+ * \returns The internal state m_state.
+ */
+ virtual E get() const
+ {
+ return m_state;
+ }
+
+ /**
+ * \brief Get the internal state m_state as a c-string.
+ *
+ * \returns Internal state m_state as a c-string.
+ */
+ virtual const char* getAsStr() const = 0;
+
+ /**
+ * \brief Reset the internal state m_state to the value of \a s or, if not supplied, to the state in E which is
+ * numerically equal to 0.
+ *
+ * \param s The state to which this instance should be reset. The default value is the member of E with a
+ * numerical value of 0.
+ *
+ * \note This call ignores the state transition logic in set() and forces the state to 0. This is not intended
+ * as a normal part of the state machine operation, but rather for reusing a state machine instance or in
+ * conditions where you need to force a change over the state machine logic. For cases where the normal state
+ * machine logic returns the state to its initial point, a verb should be created which uses set() and is
+ * subjected to the transition logic and checking of set().
+ */
+ virtual void reset(const E s = E(0))
+ {
+ m_state = s;
+ }
+
+ /**
+ * \brief Stream the string representation of the internal state m_state.
+ *
+ * \param os Stream to which the string representation of the internal state m_state will be sent.
+ */
+ virtual void toStream(std::ostream& os = std::cout) const
+ {
+ os << getAsStr();
+ }
+
+protected:
+ E m_state; ///< Local state of this state machine instance.
+
+ /**
+ * \brief Set (or change) the value of m_state. This function must implement the state machine checks for
+ * legal state change transitions, and throw an exception if an illegal state transition is requested.
+ *
+ * \param s State to which this machine should be changed.
+ */
+ virtual void set(const E s) = 0;
+
+ /**
+ * \brief Compare the state \a s with the current state.
+ *
+ * \returns \b true if \a s is the same as internal state m_state, \b false otherwise.
+ */
+ virtual bool is(const E s) const
+ {
+ return m_state == s;
+ }
+
+};
+
+}}} // namespace qpid::asyncStore::jrnl2
+
+#endif // qpid_asyncStore_jrnl2_State_h_