X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=ETL%2Ftrunk%2FETL%2F_smach.h;h=99a7320472de952d09347ce018ec8806d29635cb;hb=9459638ad6797b8139f1e9f0715c96076dbf0890;hp=24f6b5e2baa032db902ef5c19370657bbb7e7db5;hpb=b3016b249333ac0ab0008d8c6c4d9029b2ff30c9;p=synfig.git diff --git a/ETL/trunk/ETL/_smach.h b/ETL/trunk/ETL/_smach.h index 24f6b5e..99a7320 100644 --- a/ETL/trunk/ETL/_smach.h +++ b/ETL/trunk/ETL/_smach.h @@ -1,9 +1,10 @@ /*! ======================================================================== ** Extended Template and Library ** State Machine Abstraction Class Implementation -** $Id: _smach.h,v 1.1.1.1 2005/01/04 01:31:48 darco Exp $ +** $Id$ ** ** Copyright (c) 2002 Robert B. Quattlebaum Jr. +** Copyright (c) 2008 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -38,7 +39,7 @@ #ifdef _MSC_VER #pragma warning (disable:4786) -#pragma warning (disable:4290) // MSVC6 doesnt like function declarations with exception specs +#pragma warning (disable:4290) // MSVC6 doesn't like function declarations with exception specs #endif //#define ETL_MUTEX_LOCK() _mutex::lock lock(mutex) @@ -65,7 +66,7 @@ public: typedef M _mutex; typedef CON context_type; - + struct egress_exception { }; struct pop_exception { }; @@ -79,7 +80,7 @@ public: RESULT_OK, //!< Event has been processed RESULT_ACCEPT, //!< The event has been explicitly accepted. RESULT_REJECT, //!< The event has been explicitly rejected. - + RESULT_END //!< Not a valid result }; @@ -89,16 +90,16 @@ public: struct event { event_key key; - + event() { } event(const event_key& key):key(key) { } - + operator event_key()const { return key; } }; - + //! Event definition class template - class event_def + class event_def_internal { // List our friends friend class smach; @@ -116,15 +117,15 @@ public: funcptr handler; // class state : public state_base { // Our parent is our friend friend class smach; - + public: - typedef event_def event_def; + typedef event_def_internal event_def; typedef T state_context_type; - + private: - + std::vector event_list; - + smach *nested; //! Nested machine event_key low,high; //! Lowest and Highest event values const char *name; //! Name of the state @@ -187,9 +188,9 @@ public: state(const char *n, smach* nest=0): nested(nest),name(n),default_handler(NULL) { } - + virtual ~state() { } - + //! Setup a nested state machine /*! A more detailed explanation needs to be written */ void set_nested_machine(smach *sm) { nested=sm; } @@ -199,19 +200,19 @@ public: //! Returns given the name of the state virtual const char *get_name() const { return name; } - + state_context_type& get_context(smach& machine) { state_context_type *context(dynamic_cast(machine.state_context)); if(context) return context; - + } //! Adds an event_def onto the list and then make sure it is sorted correctly. void insert(const event_def &x) - { + { // If this is our first event_def, // setup the high and low values. if(!event_list.size()) @@ -227,29 +228,29 @@ public: if(high::iterator find(const event_key &x) { return binary_find(event_list.begin(),event_list.end(),x); } typename std::vector::const_iterator find(const event_key &x)const { return binary_find(event_list.begin(),event_list.end(),x); } - + protected: - + virtual void* enter_state(context_type* machine_context)const { return new state_context_type(machine_context); } - + virtual bool leave_state(void* x)const { state_context_type* state_context(reinterpret_cast(x)); delete state_context; return true; } - + virtual event_result process_event(void* x,const event& id)const { state_context_type* state_context(reinterpret_cast(x)); - + // Check for nested machine in state if(nested) { @@ -257,27 +258,27 @@ public: if(ret!=RESULT_OK) return ret; } - + // Quick test to make sure that the // given event is in the state if(id.key::const_iterator iter(find(id.key)); - + // If search results were negative, fail. if(iter->id!=id.key) return RESULT_OK; - + // Execute event function event_result ret((state_context->*(iter->handler))(id)); - + if(ret==RESULT_OK && default_handler) ret=(state_context->*(default_handler))(id); - + return ret; - } + } }; private: @@ -291,14 +292,14 @@ public: // this really should be private private: context_type* machine_context; //!< Machine Context - + const state_base* default_state; void* default_context; #ifdef ETL_MUTEX_LOCK _mutex mutex; #endif - + //! State stack data const state_base* state_stack[SMACH_STATE_STACK_SIZE]; void* state_context_stack[SMACH_STATE_STACK_SIZE]; @@ -319,7 +320,7 @@ public: return default_state->get_name(); return 0; } - + //! Determines if a given event result is an error /*! This function allows us to quickly see if an event_result contained an error */ @@ -338,14 +339,14 @@ public: const state_base *prev_state=default_state; // If we are already in a state, leave it and - // colapse the state stack + // collapse the state stack if(default_state) default_state->leave_state(default_context); // Set this as our current state default_state=nextstate; default_context=0; - + // Attempt to enter the state if(default_state) { @@ -362,12 +363,12 @@ public: // If we had a previous state, enter it if(default_state) default_context=default_state->enter_state(machine_context); - + // At this point we are not in the // requested state, so return failure return false; } - + //! Leaves the current state /*! Effectively makes the state_depth() function return zero. */ bool @@ -381,22 +382,22 @@ public: while(states_on_stack) pop_state(); // If we are not in a state, then I guess - // we were succesful. + // we were successful. if(!curr_state) return true; // Grab the return value from the exit function bool ret=true; - + const state_base* old_state=curr_state; void *old_context=state_context; - // Clear out the current state and it's state_context + // Clear out the current state and its state_context curr_state=0;state_context=0; // Leave the state return old_state->leave_state(old_context); - + return ret; } @@ -416,14 +417,14 @@ public: const state_base *prev_state=curr_state; // If we are already in a state, leave it and - // colapse the state stack + // collapse the state stack if(curr_state) egress(); // Set this as our current state curr_state=nextstate; state_context=0; - + // Attempt to enter the state state_context=curr_state->enter_state(machine_context); if(state_context) @@ -435,7 +436,7 @@ public: // If we had a previous state, enter it if(curr_state) state_context=curr_state->enter_state(machine_context); - + // At this point we are not in the // requested state, so return failure return false; @@ -499,13 +500,13 @@ public: { const state_base* old_state=curr_state; void *old_context=state_context; - + // Pop previous state off of stack --states_on_stack; curr_state=state_stack[states_on_stack]; state_context=state_context_stack[states_on_stack]; - old_state->leave_state(old_context); + old_state->leave_state(old_context); } else // If there are no states on stack, just egress egress(); @@ -522,7 +523,7 @@ public: default_context(0), states_on_stack(0) { } - + //! The destructor ~smach() { @@ -531,7 +532,7 @@ public: if(default_state) default_state->leave_state(default_context); } - + //! Sets up a child state machine /*! A child state machine runs in parallel with its parent, and gets event priority. This @@ -544,7 +545,7 @@ public: #endif child=x; } - + //! Returns the number states currently active int state_depth() @@ -552,7 +553,7 @@ public: event_result process_event(const event_key& id) { return process_event(event(id)); } - + //! Process an event event_result process_event(const event& id) @@ -560,25 +561,25 @@ public: #ifdef ETL_MUTEX_LOCK ETL_MUTEX_LOCK(); #endif - + event_result ret(RESULT_OK); - + // Check for child machine if(child) - { + { ret=child->process_event(id); if(ret!=RESULT_OK) return ret; } - + try - { + { if(curr_state) ret=curr_state->process_event(state_context,id); - + if(ret==RESULT_OK) return default_state->process_event(default_context,id); - + return ret; } catch(egress_exception) { return egress()?RESULT_ACCEPT:RESULT_ERROR; }