Created
May 13, 2016 21:06
-
-
Save eskil/5f4f572da98121bd157e49b6b391ed2a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "statemachines.h" | |
#include <fstream> | |
//********************************************************************************************* | |
namespace simple_test { | |
/* | |
#define TRY_CLASS_PTR_STATES 0 | |
#define TRY_CLASS_STATES 0 | |
#define TRY_INT_STATES 1 | |
#define TRY_CHAR_PTR_STATES 0 | |
*/ | |
#if TRY_CLASS_PTR_STATES || TRY_CLASS_STATES | |
class _state { | |
public: | |
_state () : m_name ("?") {} | |
_state (std::string n) : m_name (n) {} | |
friend std::ostream& operator<< (std::ostream& o, const _state *i); | |
friend std::ostream& operator<< (std::ostream& o, const _state &i); | |
std::string m_name; | |
}; | |
class _initial_state : public _state { public: _initial_state () : _state ("initial state") {} }; | |
class _fail_state : public _state { public: _fail_state () : _state ("fail state") {} }; | |
class _one_state : public _state { public: _one_state () : _state ("one state") {} }; | |
class _end_state : public _state { public: _end_state () : _state ("end state") {} }; | |
class _loop_1_state : public _state { public: _loop_1_state () : _state ("loop 1 state") {} }; | |
class _loop_2_state : public _state { public: _loop_2_state () : _state ("loop 2 state") {} }; | |
_state *g_initial_state = new _initial_state; | |
_state *g_fail_state = new _fail_state; | |
_state *g_one_state = new _one_state; | |
_state *g_end_state = new _end_state; | |
_state *g_loop_1_state = new _loop_1_state; | |
_state *g_loop_2_state = new _loop_2_state; | |
std::ostream& operator<< (std::ostream& o, const _state *i) { | |
return o << i->m_name; | |
} | |
std::ostream& operator<< (std::ostream& o, const _state &i) { | |
return o << i.m_name; | |
} | |
#endif | |
#if TRY_CLASS_PTR_STATES | |
#define initial_state g_initial_state | |
#define fail_state g_fail_state | |
#define one_state g_end_state | |
#define end_state g_one_state | |
#define loop_1_state g_loop_1_state | |
#define loop_2_state g_loop_2_state | |
typedef const _state* my_state_type; | |
#endif | |
#if TRY_CLASS_STATES | |
#define initial_state _initial_state () | |
#define fail_state _fail_state () | |
#define one_state _one_state () | |
#define end_state _end_state () | |
#define loop_1_state _loop_1_state () | |
#define loop_2_state _loop_2_state () | |
typedef _state my_state_type; | |
// since the statemachine will have a shitload of instances (one pr. edge end point), we need to be | |
// able to compare them | |
bool operator==(const my_state_type &a, const my_state_type &b) { return a.m_name == b.m_name; } | |
bool operator<(const my_state_type &a, const my_state_type &b) { return a.m_name < b.m_name; } | |
#endif | |
#if TRY_INT_STATES | |
typedef enum { | |
initial_state, one_state, end_state, loop_1_state, loop_2_state, fail_state | |
} my_state_type; | |
std::ostream& operator<< (std::ostream& o, my_state_type i) { | |
if (i == initial_state) return o << "initial_state"; | |
if (i == fail_state) return o << "fail_state"; | |
if (i == one_state) return o << "one_state"; | |
if (i == end_state) return o << "end_state"; | |
if (i == loop_2_state) return o << "loop_2_state"; | |
if (i == loop_1_state) return o << "loop_1_state"; | |
return o << "?"; | |
} | |
#endif | |
#if TRY_CHAR_PTR_STATES | |
#define initial_state "initial_state" | |
#define fail_state "fail_state" | |
#define one_state "one_state" | |
#define end_state "end_state" | |
#define loop_1_state "loop_1_state" | |
#define loop_2_state "loop_2_state" | |
typedef char* my_state_type; | |
#endif | |
class simple; | |
typedef statemachines::traits<my_state_type, threads::single_threaded> my_traits; | |
class simple : public statemachines::statemachine<simple, my_traits> { | |
public: | |
class generic_event : public event_t {}; | |
class one_event : public event_t { | |
public: | |
one_event (std::string msg) : m_message (msg) {} | |
std::string m_message; | |
}; | |
class loop_event : public event_t {}; | |
class failure_event : public event_t {}; | |
simple () { | |
*this << graphviz_t ("test_graph") | |
<< begin_t (initial_state) | |
//------------------------+---------------+-------------+---------------------------+--------------------- | |
// Event From-State To-State Action Description | |
<< edge_t<one_event> (initial_state, one_state, &simple::action, "we got a 1") | |
<< edge_t<failure_event> (initial_state, fail_state) | |
<< edge_t<loop_event> (initial_state, loop_1_state, "got a loop event") | |
<< edge_t<loop_event> (one_state, loop_2_state, &simple::loop_2_action, "got a loop event") | |
<< edge_t<loop_event> (loop_1_state, loop_2_state, &simple::loop_2_action) | |
<< edge_t<loop_event> (loop_2_state, loop_1_state, "do a loop") | |
<< edge_t<generic_event> (fail_state, end_state) | |
<< edge_t<generic_event> (one_state, end_state, &simple::end_action, "") | |
<< edge_t<generic_event> (loop_1_state, end_state, &simple::end_action, "generic") | |
<< edge_t<generic_event> (loop_2_state, end_state, &simple::end_action, "generic"); | |
//------------------------+---------------+-------------+---------------------------+--------------------- | |
} | |
void action (const one_event &foo) { | |
printf ("action for one_event : %s\n", foo.m_message.c_str ()); | |
m_count ++; | |
} | |
void end_action (const generic_event &foo) { | |
printf ("reached the end of the line\n"); | |
m_count ++; | |
} | |
void loop_2_action (const loop_event &foo) { | |
printf ("loop\n"); | |
prepost_event (new loop_event); | |
m_count ++; | |
} | |
void run (const std::string &name) { | |
m_count = 0; | |
// exercise it a bit | |
post_event (new one_event ("hello world!")); | |
post_event (new loop_event); | |
post_event (new loop_event); | |
post_event (new generic_event); | |
while (handle_event ()) { } | |
assert (m_count == 4); | |
save_to_postscript (name); | |
} | |
void save_to_postscript (std::string name) { | |
// create ps file showing state machine | |
name.erase (0, 2); | |
std::ofstream dotfile; | |
dotfile.open ((name + ".dot").c_str ()); | |
dotfile << toGraphViz (); | |
dotfile.close (); | |
std::string cmd ("dot -Tps -o "); | |
cmd += (name + ".ps " + name + ".dot "); | |
std::cout << cmd << std::endl; | |
system (cmd.c_str ()); | |
} | |
private: | |
int m_count; | |
}; | |
}; | |
//********************************************************************************************* | |
int main (int argc, char *argv[]) { | |
printf ("\nstatemachine_test\n--------------------------------------------\n"); | |
simple_test::simple fsm_test; | |
fsm_test.run (argv[0]); | |
printf ("--------------------------------------------\n"); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment