t-suw****@users*****
t-suw****@users*****
2007年 9月 24日 (月) 18:24:55 JST
Index: AquaSKK/GenericStateMachine.h diff -u AquaSKK/GenericStateMachine.h:1.1.2.1 AquaSKK/GenericStateMachine.h:removed --- AquaSKK/GenericStateMachine.h:1.1.2.1 Sat Feb 3 16:53:29 2007 +++ AquaSKK/GenericStateMachine.h Mon Sep 24 18:24:55 2007 @@ -1,503 +0,0 @@ -/* -*- C++ -*- - - Generic State Machine Library for C++. - - Copyright (c) 2006, Tomotaka SUWA <t.suw****@mac*****> All rights - reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of the "Generic State Machine Library for C++" nor - the names of its contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - $Id: GenericStateMachine.h,v 1.1.2.1 2007/02/03 07:53:29 t-suwa Exp $ -*/ - -#ifndef INC__GenericStateMachine__ -#define INC__GenericStateMachine__ - -#include <cassert> -#include <vector> -#include <list> -#include <algorithm> -#include <functional> - -namespace statemachinecxx_sourceforge_jp { - // ====================================================================== - // event types - // ====================================================================== - enum EventTypes { - EXIT_EVENT = -3, - INIT_EVENT = -2, - ENTRY_EVENT = -1, - PROBE = 0, - USER_EVENT = 1 - }; - - // ====================================================================== - // Event - // ====================================================================== - template <class ParamType> - class GenericEvent { - int type_; - ParamType param_; - - public: - GenericEvent() {} - GenericEvent(int type) : type_(type) {} - GenericEvent(int type, const ParamType& arg) : type_(type), param_(arg) {} - - operator int() const { return type_; } - void SetType(int type) { type_ = type;} - - const ParamType& Param() const { return param_; } - void SetParam(const ParamType& arg) { param_ = arg; } - - static GenericEvent& Probe() { static GenericEvent evt(PROBE); return evt; } - static GenericEvent& Entry() { static GenericEvent evt(ENTRY_EVENT); return evt; } - static GenericEvent& Exit() { static GenericEvent evt(EXIT_EVENT); return evt; } - static GenericEvent& Init() { static GenericEvent evt(INIT_EVENT); return evt; } - }; - - // ====================================================================== - // State - // ====================================================================== - template <class StateContainer> - class GenericState { - enum StateType { - UNKNOWN, - SUPER, - INITIAL, - SHALLOW_HISTORY, - DEEP_HISTORY, - TRANSITION, - FORWARD, - DEEP_FORWARD, - SAVE_HISTORY, - DEFER_EVENT - }; - - typedef typename StateContainer::Handler Handler; - - int type_; - Handler handler_; - - GenericState(StateType type, Handler handler) : type_(type), handler_(handler) {} - - public: - GenericState() : type_(UNKNOWN), handler_(0) {} - GenericState(Handler handler) : type_(UNKNOWN), handler_(handler) {} - - operator Handler() const { return handler_; } - - bool IsSuper() const { return type_ == SUPER; } - bool IsInitial() const { return type_ == INITIAL; } - bool IsShallowHistory() const { return type_ == SHALLOW_HISTORY; } - bool IsDeepHistory() const { return type_ == DEEP_HISTORY; } - bool IsTransition() const { return type_ == TRANSITION; } - bool IsForward() const { return type_ == FORWARD; } - bool IsDeepForward() const { return type_ == DEEP_FORWARD; } - bool IsSaveHistory() const { return type_ == SAVE_HISTORY; } - bool IsDeferEvent() const { return type_ == DEFER_EVENT; } - - static GenericState Super(Handler handler) { return GenericState(SUPER, handler); } - static GenericState Initial(Handler handler) { return GenericState(INITIAL, handler); } - static GenericState ShallowHistory(Handler handler) { return GenericState(SHALLOW_HISTORY, handler); } - static GenericState DeepHistory(Handler handler) { return GenericState(DEEP_HISTORY, handler); } - static GenericState Transition(Handler handler) { return GenericState(TRANSITION, handler); } - static GenericState Forward(Handler handler) { return GenericState(FORWARD, handler); } - static GenericState DeepForward(Handler handler) { return GenericState(DEEP_FORWARD, handler); } - static GenericState SaveHistory() { return GenericState(SAVE_HISTORY, 0); } - static GenericState DeferEvent() { return GenericState(DEFER_EVENT, 0); } - }; - - // ====================================================================== - // State History - // ====================================================================== - template <typename Handler> - class GenericStateHistory { - typedef std::pair<Handler, Handler> Entry; - std::vector<Handler> keys_; - std::vector<Entry> values_; - - enum HistoryType { SHALLOW, DEEP }; - - int lookup(const Handler key) const { - typename std::vector<Handler>::const_iterator iter = std::find(keys_.begin(), keys_.end(), key); - - if(iter == keys_.end()) return -1; - - return iter - keys_.begin(); - } - - const Handler get(Handler key, HistoryType type) const { - int pos = lookup(key); - - if(pos < 0) return 0; - - return (type == SHALLOW) ? values_[pos].first : values_[pos].second; - } - - public: - void Save(Handler key, Handler shallow, Handler deep) { - int pos = lookup(key); - Entry history(std::make_pair(shallow, deep)); - - if(pos < 0) { - keys_.push_back(key); - values_.push_back(history); - } else { - values_[pos] = history; - } - } - - const Handler Shallow(Handler key) const { - return get(key, SHALLOW); - } - - const Handler Deep(Handler key) const { - return get(key, DEEP); - } - }; - - // ====================================================================== - // Deferred Event - // ====================================================================== - template <class StateContainer> - class GenericDeferEvent { - typedef typename StateContainer::Event Event; - typedef typename StateContainer::Handler Handler; - typedef std::pair<Handler, Event> Entry; - std::list<Entry> queue_; - - struct NotEqual : public std::unary_function<Entry, bool> { - const Handler key; - NotEqual(Handler arg) : key(arg) {} - bool operator()(const Entry& entry) const { - return key != entry.first; - } - }; - - public: - void Enqueue(const Handler key, const Event& event) { - queue_.push_back(std::make_pair(key, event)); - } - - bool Dequeue(const Handler key, Event& event) { - typename std::list<Entry>::iterator iter = std::find_if(queue_.begin(), queue_.end(), NotEqual(key)); - - if(iter != queue_.end()) { - event = iter->second; - queue_.erase(iter); - return true; - } - - return false; - } - }; - - // ====================================================================== - // Standard Invoker - // ====================================================================== - template <class StateContainer> - class StandardInvoker { - typedef typename StateContainer::Handler Handler; - typedef typename StateContainer::Event Event; - typedef typename StateContainer::State State; - - StateContainer& instance_; - - public: - StandardInvoker(StateContainer& obj) : instance_(obj) {} - - State operator()(const Handler handler, const Event& event) { - assert(handler != 0 && "Invalid handler address."); - return (instance_.*handler)(event); - } - }; - - // ====================================================================== - // State Machine - // ====================================================================== - template <class StateContainer, template <class StateContainer> class Invoker = StandardInvoker> - class GenericStateMachine { - typedef typename StateContainer::Handler Handler; - typedef typename StateContainer::Event Event; - typedef typename StateContainer::State State; - typedef typename StateContainer::Output Output; - - StateContainer container_; - - Handler top_; - Handler active_; - Handler prior_; - - Invoker<StateContainer> invoke_; - GenericStateHistory<Handler> history_; - GenericDeferEvent<StateContainer> queue_; - - Event defer_; - - typedef typename std::vector<Handler> Path; - typedef typename Path::iterator PathIterator; - - Path path_; - - // ------------------------------------------------------------ - // primitive functions - // ------------------------------------------------------------ - State getSuperState(const Handler handler) { return invoke_(handler, Event::Probe()); } - State entryAction(const Handler handler) { return invoke_(handler, Event::Entry()); } - State initialTransition(const Handler handler) { return invoke_(handler, Event::Init()); } - State exitAction(const Handler handler) { - State result = invoke_(handler, Event::Exit()); - - if(result.IsSaveHistory()) { - assert(prior_ != 0 && "Shallow history not found."); - history_.Save(handler, prior_, active_); - } - - prior_ = handler; - - return result; - } - - // ------------------------------------------------------------ - // trigger initial transition - // ------------------------------------------------------------ - void initialize(const State& target) { - State state; - - active_ = target; - - for(state = initialTransition(active_); state.IsInitial() || state.IsShallowHistory(); - state = initialTransition(active_)) { - assert(state != active_ && "Infinete loop detected. Check INIT_EVENT."); - assert((getSuperState(state) == active_ || getSuperState(state) == getSuperState(active_)) - && "Initial transition must go same level or one level deep."); - - if(state.IsShallowHistory()) { - Handler shallow = history_.Shallow(active_); - if(!shallow) { - history_.Save(active_, state, 0); // first time - active_ = state; - } else { - active_ = shallow; - } - } else { - active_ = state; - } - - entryAction(active_); - } - - assert(state.IsSuper() && "Initial transition must be ended by 'return State::Super(state);'."); - } - - // ------------------------------------------------------------ - // trigger transition - // ------------------------------------------------------------ - void transition(const Handler source, const Handler target) { - assert(target != top_ && "You can not transition to TopState."); - - Handler tmp; - - // exit to source - for(tmp = active_, prior_ = 0; tmp != source; tmp = getSuperState(tmp)) { - exitAction(tmp); - } - - // exit to LCA(Least Common Ancestor) and record path to target - do { - path_.push_back(target); - - // (a) self transition - if(source == target) { - exitAction(source); - break; - } - - // (b) go into substate(one level) - Handler targetSuper = getSuperState(target); - if(source == targetSuper) { - break; - } - - // (c) balanced transition - Handler sourceSuper = getSuperState(source); - if(sourceSuper == targetSuper) { - exitAction(source); - break; - } - - // (d) exit from substate(one level) - if(sourceSuper == target) { - exitAction(source); - path_.clear(); - break; - } - - // (e) go into substate(multiple level) - path_.push_back(targetSuper); - for(tmp = getSuperState(targetSuper); tmp != 0; tmp = getSuperState(tmp)) { - if(source == tmp) { - break; - } - path_.push_back(tmp); - } - if(tmp != 0) break; - - exitAction(source); - - struct check { - static bool exist(Path& path, const Handler handler) { - PathIterator iter = std::find(path.begin(), path.end(), handler); - if(iter != path.end()) { - path.erase(iter, path.end()); - return true; - } - return false; - } - }; - - // (f) unbalanced transition - if(check::exist(path_, sourceSuper)) { - break; - } - - // (g) exit from substate(multiple level) - for(tmp = sourceSuper; tmp != 0; tmp = getSuperState(tmp)) { - if(check::exist(path_, tmp)) { - break; - } - exitAction(tmp); - } - if(tmp != 0) break; - - assert(0 && "Invalid state transition form."); - } while(0); - - // go into target - while(!path_.empty()) { - entryAction(path_.back()); - path_.pop_back(); - } - } - - public: - GenericStateMachine() : top_(&StateContainer::TopState), active_(0), prior_(0), invoke_(container_) {} - - ~GenericStateMachine() { - for(Handler tmp = active_; tmp != 0; tmp = getSuperState(tmp)) { - exitAction(tmp); - } - } - - void Start() { - assert(active_ == 0 && "You can't call Start() twice."); - - initialize(State::Initial(top_)); - } - - void Dispatch(const Event& event) { - assert(active_ != 0 && "You must call Start() before call Dispatch()."); - - State next; - - for(Handler source = active_; source != 0; source = next) { - next = invoke_(source, event); - - if(next.IsDeferEvent()) { - queue_.Enqueue(next, event); - break; - } - - if(next.IsForward() || next.IsDeepForward()) { - if(next.IsDeepForward()) { - next = history_.Deep(next); - assert(next != 0 && "Deep history not found."); - } - - transition(source, next); - initialize(next); - continue; - } - - if(next.IsTransition() || next.IsDeepHistory()) { - if(next.IsDeepHistory()) { - next = history_.Deep(next); - assert(next != 0 && "Deep history not found."); - } - - transition(source, next); - initialize(next); - - while(queue_.Dequeue(next, defer_)) { - Dispatch(defer_); // recursion - } - break; - } - - assert(!next.IsShallowHistory() && !next.IsSaveHistory() && !next.IsInitial() && "Invalid state."); - } - } - - const Output& Result() const { - return container_.Result(); - } - }; - -} // statemachinecxx_sourceforge_jp - -// ====================================================================== -// helper macro -// ====================================================================== - -#define DECLARE_ImportantTypes(container, param, result) \ - typedef GenericState<container> State; \ - typedef GenericEvent<param> Event; \ - typedef State (container::*Handler)(const Event&); \ - typedef result Output; - -#define DECLARE_TopState(container, initial) \ - State TopState(const Event& event) { \ - switch(event) { \ - case INIT_EVENT: \ - return State::Initial(&container::initial); \ - } \ - return 0; \ - } - -#define DECLARE_StateContainer(container, param, result, initial) \ - DECLARE_ImportantTypes(container, param, result) \ - DECLARE_TopState(container, initial) - -#define IMPLEMENT_StateContainer(container) \ - typedef container::State State; \ - typedef container::Event Event; - -#endif