tkem / fsmlite Goto Github PK
View Code? Open in Web Editor NEWLightweight finite state machine framework for C++11
License: MIT License
Lightweight finite state machine framework for C++11
License: MIT License
process_event()
must not be called from within an action or guard.
Maybe assert this with #ifndef NDEBUG
(flag set on entry and cleared on exit).
Plain fsm::row
should be reserved for something more user-friendly, e.g. placeholder parameters in C++17.
test_rows.cpp
(more methodical tests, assure all variants are covered)See dev/travis branch. Needs to be fixed ASAP.
the introduction says it's for cpp11, but in src file it uses features which is newer than cpp11.
I have a use case where I often need to validate transitions using multiple guards. For now, this requires an extra member function that wraps other boolean checks such that a single bool output is provided to the fsm API. It would be awesome to reduce some of the boilerplate by supporting the ability to provide a list of guards that need to all be AND'd together to validate the transition. Then on the handle_event
, here, you'd just check for each of the provided guards before proceeding. This pattern is similar to the API provided by the python transitions lib.
fsmlite is definitely a C++ lib. Why use the .h extension, indicating that it will be a c-lib? The common way is to either have no extension (as per STL), or to have .hpp (as per Boost), take your pick, but not .h.
Maybe also add VC++ project files, unit tests.
MSVC requires /Zc:__cplusplus
to correctly set __cplusplus
:
https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
However, there is also _MSVC_LANG
:
_MSVC_LANG Defined as an integer literal that specifies the C++ language standard targeted by the compiler. It's set only in code compiled as C++. The macro is the integer literal value 201402L by default, or when the /std:c++14 compiler option is specified. The macro is set to 201703L if the /std:c++17 compiler option is specified. It's set to a higher, unspecified value when the /std:c++latest option is specified. Otherwise, the macro is undefined. The _MSVC_LANG macro and /std (Specify Language Standard Version) compiler options are available beginning in Visual Studio 2015 Update 3.
https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-160
Consider checking for specific C++ versions/features using both __cplusplus
and _MSVC_LANG
, so users do not have to remember turning on /Zc:__cplusplus
.
Hi, thanks for all the work on this project!
I'm building and using fsmlite via CMake. This way I am able to find, link and test fsmlite on multiple platforms. I was wondering if a PR for support of CMake would be considered? Perhaps even replacing Make.
That way you could easily build and test using MSVC, GCC, Clang or any other compiler. To be able to build the tests with MSVC >=19.14, a change was required for successful compilation, basically:
- friend class fsm; // base class needs access to transition_table
+ friend class fsmlite::fsm<state_machine>; // base class needs access to transition_table
After that, testing is easy as ctest -C Debug
Test project C:/dev/third_party/fsmlite/build
Start 1: fsmlite_tests_test_basic_row
1/9 Test #1: fsmlite_tests_test_basic_row ..... Passed 1.43 sec
Start 2: fsmlite_tests_test_mem_fn_row
2/9 Test #2: fsmlite_tests_test_mem_fn_row .... Passed 1.44 sec
Start 3: fsmlite_tests_test_notrans
3/9 Test #3: fsmlite_tests_test_notrans ....... Passed 1.63 sec
Start 4: fsmlite_tests_test_player
4/9 Test #4: fsmlite_tests_test_player ........ Passed 1.63 sec
Start 5: fsmlite_tests_test_recursive
5/9 Test #5: fsmlite_tests_test_recursive ..... Passed 2.60 sec
Start 6: fsmlite_tests_test_row
6/9 Test #6: fsmlite_tests_test_row ........... Passed 0.07 sec
Start 7: fsmlite_tests_test_scoped
7/9 Test #7: fsmlite_tests_test_scoped ........ Passed 0.05 sec
Start 8: fsmlite_tests_test_shared
8/9 Test #8: fsmlite_tests_test_shared ........ Passed 1.45 sec
Start 9: fsmlite_tests_test_traits
9/9 Test #9: fsmlite_tests_test_traits ........ Passed 0.07 sec
100% tests passed, 0 tests failed out of 9
Total Test time (real) = 10.46 sec
It's kind of awkward to use, and with C++17 serves no real purpose any more.
Also think about renaming mem_fn_row
to simply row
on C++11, should be reasonably forward-compatible with the C++17 implementation (except for overloaded member functions).
[ ] Sphinx version information should be extracted from configure.ac
.
[ ] Presence of doxygen
and sphinx-build
should be checked in autoconf.
I aprreciate the code you shared. But it seems that every time this fsm handles an event, it needs to search the transition table. So the time complexity for each call of process_event
is O(N) (N is the count of rows) , not O(1), which makes this fsm unpractical .
As stated in #5, process_event()
must not be called recursively. Since this is a common pattern, especially with multiple FSMs passing events to each other, a "queuing" FSM type should be added.
Hi,
Great lib, works out of the box. Almost.
Test program with #include "fsm.h"
g++ -g -Wall -Wextra -Werror -std=c++17 prog.cc -o prog
fsm.h:242:47: error: unused parameter ‘event’ [-Werror=unused-parameter]
Fix to silent compiler warning:
--- fsm.h 2020-06-05 11:15:19.387923805 +0200
+++ fsm-patched.h 2020-06-05 11:30:52.649638975 +0200
@@ -240,7 +240,7 @@
*/
template<class Event>
state_type no_transition(const Event& event) {
- return m_state;
+ (void)event; return m_state;
}
Best Regards,
Johan
Compilation without errors, the following link errors arise:
1>------ Rebuild All started: Project: test, Configuration: Release x64 ------
1>test_player_main.obj : error LNK2019: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::open_drawer(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::open_drawer(struct player::open_close const &)>::value" (?value@?$mem_fn_action@Uopen_close@player@@$1?open_drawer@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A) referenced in function "public: static void __cdecl fsmlite::fsm<class player,int>::basic_row<0,struct player::open_close,1,struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::open_drawer(struct player::open_close const &)>::type,&public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::open_drawer(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::open_drawer(struct player::open_close const &)>::value,struct fsmlite::fsm<class player,int>::no_guard::type,&public: static struct fsmlite::fsm<class player,int>::no_guard::type fsmlite::fsm<class player,int>::no_guard::value>::process_event(class player &,struct player::open_close const &)" (?process_event@?$basic_row@$0A@Uopen_close@player@@$00Utype@?$mem_fn_action@Uopen_close@player@@$1?open_drawer@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@$1?value@456@2U3456@AU3?$no_guard@Uopen_close@player@@@56@$1?7856@2U3856@A@?$fsm@Vplayer@@h@fsmlite@@SAXAEAVplayer@@AEBUopen_close@4@@z)
1>test_player_main.obj : error LNK2019: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::close_drawer(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::close_drawer(struct player::open_close const &)>::value" (?value@?$mem_fn_action@Uopen_close@player@@$1?close_drawer@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A) referenced in function "public: static void __cdecl fsmlite::fsm<class player,int>::basic_row<1,struct player::open_close,2,struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::close_drawer(struct player::open_close const &)>::type,&public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::close_drawer(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::close_drawer(struct player::open_close const &)>::value,struct fsmlite::fsm<class player,int>::no_guard::type,&public: static struct fsmlite::fsm<class player,int>::no_guard::type fsmlite::fsm<class player,int>::no_guard::value>::process_event(class player &,struct player::open_close const &)" (?process_event@?$basic_row@$00Uopen_close@player@@$01Utype@?$mem_fn_action@Uopen_close@player@@$1?close_drawer@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@$1?value@456@2U3456@AU3?$no_guard@Uopen_close@player@@@56@$1?7856@2U3856@A@?$fsm@Vplayer@@h@fsmlite@@SAXAEAVplayer@@AEBUopen_close@4@@z)
1>test_player_main.obj : error LNK2019: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::stop_and_open(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::stop_and_open(struct player::open_close const &)>::value" (?value@?$mem_fn_action@Uopen_close@player@@$1?stop_and_open@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A) referenced in function "public: static void __cdecl fsmlite::fsm<class player,int>::basic_row<3,struct player::open_close,1,struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::stop_and_open(struct player::open_close const &)>::type,&public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::stop_and_open(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::stop_and_open(struct player::open_close const &)>::value,struct fsmlite::fsm<class player,int>::no_guard::type,&public: static struct fsmlite::fsm<class player,int>::no_guard::type fsmlite::fsm<class player,int>::no_guard::value>::process_event(class player &,struct player::open_close const &)" (?process_event@?$basic_row@$02Uopen_close@player@@$00Utype@?$mem_fn_action@Uopen_close@player@@$1?stop_and_open@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@$1?value@456@2U3456@AU3?$no_guard@Uopen_close@player@@@56@$1?7856@2U3856@A@?$fsm@Vplayer@@h@fsmlite@@SAXAEAVplayer@@AEBUopen_close@4@@z)
1>test_player_main.obj : error LNK2019: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::cd_detected,&private: void __cdecl player::store_cd_info(struct player::cd_detected const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::cd_detected,&private: void __cdecl player::store_cd_info(struct player::cd_detected const &)>::value" (?value@?$mem_fn_action@Ucd_detected@player@@$1?store_cd_info@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A) referenced in function "public: static void __cdecl fsmlite::fsm<class player,int>::basic_row<2,struct player::cd_detected,0,struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::cd_detected,&private: void __cdecl player::store_cd_info(struct player::cd_detected const &)>::type,&public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::cd_detected,&private: void __cdecl player::store_cd_info(struct player::cd_detected const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::cd_detected,&private: void __cdecl player::store_cd_info(struct player::cd_detected const &)>::value,struct fsmlite::fsm<class player,int>::no_guard::type,&public: static struct fsmlite::fsm<class player,int>::no_guard::type fsmlite::fsm<class player,int>::no_guard::value>::process_event(class player &,struct player::cd_detected const &)" (?process_event@?$basic_row@$01Ucd_detected@player@@$0A@Utype@?$mem_fn_action@Ucd_detected@player@@$1?store_cd_info@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@$1?value@456@2U3456@AU3?$no_guard@Ucd_detected@player@@@56@$1?7856@2U3856@A@?$fsm@Vplayer@@h@fsmlite@@SAXAEAVplayer@@AEBUcd_detected@4@@z)
1>test_player_main.obj : error LNK2019: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::start_playback(struct player::play const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::start_playback(struct player::play const &)>::value" (?value@?$mem_fn_action@Uplay@player@@$1?start_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A) referenced in function "public: static void __cdecl fsmlite::fsm<class player,int>::basic_row<0,struct player::play,3,struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::start_playback(struct player::play const &)>::type,&public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::start_playback(struct player::play const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::start_playback(struct player::play const &)>::value,struct fsmlite::fsm<class player,int>::no_guard::type,&public: static struct fsmlite::fsm<class player,int>::no_guard::type fsmlite::fsm<class player,int>::no_guard::value>::process_event(class player &,struct player::play const &)" (?process_event@?$basic_row@$0A@Uplay@player@@$02Utype@?$mem_fn_action@Uplay@player@@$1?start_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@$1?value@456@2U3456@AU3?$no_guard@Uplay@player@@@56@$1?7856@2U3856@A@?$fsm@Vplayer@@h@fsmlite@@SAXAEAVplayer@@AEBUplay@4@@z)
1>test_player_main.obj : error LNK2019: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::resume_playback(struct player::play const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::resume_playback(struct player::play const &)>::value" (?value@?$mem_fn_action@Uplay@player@@$1?resume_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A) referenced in function "public: static void __cdecl fsmlite::fsm<class player,int>::basic_row<4,struct player::play,3,struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::resume_playback(struct player::play const &)>::type,&public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::resume_playback(struct player::play const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::resume_playback(struct player::play const &)>::value,struct fsmlite::fsm<class player,int>::no_guard::type,&public: static struct fsmlite::fsm<class player,int>::no_guard::type fsmlite::fsm<class player,int>::no_guard::value>::process_event(class player &,struct player::play const &)" (?process_event@?$basic_row@$03Uplay@player@@$02Utype@?$mem_fn_action@Uplay@player@@$1?resume_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@$1?value@456@2U3456@AU3?$no_guard@Uplay@player@@@56@$1?7856@2U3856@A@?$fsm@Vplayer@@h@fsmlite@@SAXAEAVplayer@@AEBUplay@4@@z)
1>test_player_main.obj : error LNK2019: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::pause,&private: void __cdecl player::pause_playback(struct player::pause const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::pause,&private: void __cdecl player::pause_playback(struct player::pause const &)>::value" (?value@?$mem_fn_action@Upause@player@@$1?pause_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A) referenced in function "public: static void __cdecl fsmlite::fsm<class player,int>::basic_row<3,struct player::pause,4,struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::pause,&private: void __cdecl player::pause_playback(struct player::pause const &)>::type,&public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::pause,&private: void __cdecl player::pause_playback(struct player::pause const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::pause,&private: void __cdecl player::pause_playback(struct player::pause const &)>::value,struct fsmlite::fsm<class player,int>::no_guard::type,&public: static struct fsmlite::fsm<class player,int>::no_guard::type fsmlite::fsm<class player,int>::no_guard::value>::process_event(class player &,struct player::pause const &)" (?process_event@?$basic_row@$02Upause@player@@$03Utype@?$mem_fn_action@Upause@player@@$1?pause_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@$1?value@456@2U3456@AU3?$no_guard@Upause@player@@@56@$1?7856@2U3856@A@?$fsm@Vplayer@@h@fsmlite@@SAXAEAVplayer@@AEBUpause@4@@z)
1> LINK : MSIL .netmodule or module compiled with /GL found; restarting link with /LTCG; add /LTCG to the link command line to improve linker performance
1>test_player_main.obj : error LNK2001: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::open_drawer(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::open_drawer(struct player::open_close const &)>::value" (?value@?$mem_fn_action@Uopen_close@player@@$1?open_drawer@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A)
1>test_player_main.obj : error LNK2001: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::close_drawer(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::close_drawer(struct player::open_close const &)>::value" (?value@?$mem_fn_action@Uopen_close@player@@$1?close_drawer@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A)
1>test_player_main.obj : error LNK2001: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::stop_and_open(struct player::open_close const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::open_close,&private: void __cdecl player::stop_and_open(struct player::open_close const &)>::value" (?value@?$mem_fn_action@Uopen_close@player@@$1?stop_and_open@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A)
1>test_player_main.obj : error LNK2001: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::cd_detected,&private: void __cdecl player::store_cd_info(struct player::cd_detected const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::cd_detected,&private: void __cdecl player::store_cd_info(struct player::cd_detected const &)>::value" (?value@?$mem_fn_action@Ucd_detected@player@@$1?store_cd_info@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A)
1>test_player_main.obj : error LNK2001: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::start_playback(struct player::play const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::start_playback(struct player::play const &)>::value" (?value@?$mem_fn_action@Uplay@player@@$1?start_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A)
1>test_player_main.obj : error LNK2001: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::resume_playback(struct player::play const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::play,&private: void __cdecl player::resume_playback(struct player::play const &)>::value" (?value@?$mem_fn_action@Uplay@player@@$1?resume_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A)
1>test_player_main.obj : error LNK2001: unresolved external symbol "public: static struct fsmlite::fsm<class player,int>::mem_fn_action<struct player::pause,&private: void __cdecl player::pause_playback(struct player::pause const &)>::type fsmlite::fsm<class player,int>::mem_fn_action<struct player::pause,&private: void __cdecl player::pause_playback(struct player::pause const &)>::value" (?value@?$mem_fn_action@Upause@player@@$1?pause_playback@2@AEAAXAEBU12@@z@?$fsm@Vplayer@@h@fsmlite@@2Utype@123@A)
1>x64\Release\test.exe : fatal error LNK1120: 7 unresolved externals
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
There are basically two separate interfaces for specifying transitions, row
which works for C++17 only, and mem_fn_row
which works since C++11. With C++17 support widely available now (except maybe for embedded), it's maybe time to drop mem_fn_row
and C++11 support altogether.
See also #21 about dropping basic_row
along the way.
A third template parameter should be added to class fsm
, which specifies a BasicLockable.
This would be locked at the start of process_event()
, so recursive invocations can be detected.
The default class should throw a logic_error
in this case, except if exceptions are disabled.
Hi,
Maybe I am missing something fundamental here.
Besides current_state()
, wouldn't it be useful to have target_state()
?
An example:
I am creating a SIP packet analyzer. At the moment I just want to save the timestamp of the incoming packet. See the transition_table
below.
As seen in the table, the same Action, SaveTimestamp()
, could be used for all packets if target_state()
could be accessed from within SaveTimestamp()
.
Best Regards,
Johan
using transition_table = table<
// Start Event Target Action Guard (optional)
// ----+-------------+---------------+---------------+-----------------------+-----------------+-
row< BEGIN, EvInvite, INVITE, &m::SaveTimestamp >, // Save INVITE ts
row< INVITE, EvInvite, INVITE, &m::SaveTimestamp >, // Save INVITE ts
row< INVITE, EvAuth407, INVITE, &m::SaveTimestamp >, // Save INVITE ts
row< INVITE, EvTrying100, TRYING, &m::SaveTimestamp >, // Save TRYING ts
row< INVITE, EvRinging180, RINGING, &m::SaveTimestamp >, // Save RINGING ts
row< INVITE, EvOk200, INVITE_OK, &m::SaveTimestamp >, // Save INVITE_OK ts
row< INVITE, EvFailureXXX, INVITE_FAILURE, &m::SaveTimestamp >, // Save INVITE_FAILURE ts
row< TRYING, EvOk200, INVITE_OK, &m::SaveTimestamp >, // Save INVITE_OK ts
row< TRYING, EvRinging180, RINGING, &m::SaveTimestamp >, // Save RINGING ts
row< TRYING, EvCancel, CANCEL, &m::SaveTimestamp >, // Save CANCEL ts
row< TRYING, EvUnsuccessful, UNSUCCESSFUL, &m::SaveTimestamp >, // Save INVITE_FAILURE ts
row< RINGING, EvOk200, INVITE_OK, &m::SaveTimestamp >, // Save INVITE_OK ts
row< RINGING, EvCancel, CANCEL, &m::SaveTimestamp >, // Save CANCEL ts
row< RINGING, EvUnsuccessful, UNSUCCESSFUL, &m::DoNothing >,
row< INVITE_OK, EvBye, BYE, &m::SaveTimestamp >, // Save BYE ts
row< BYE, EvOk200, BYE_OK, &m::SaveTimestamp >, // Save BYE_OK ts
row< CANCEL, EvOk200, CANCEL_OK, &m::SaveTimestamp >, // Save CANCEL_OK ts
row< BYE_OK, EvAny, END, &m::DoNothing >,
row< CANCEL_OK, EvAny, END, &m::DoNothing >,
row< UNSUCCESSFUL, EvAny, END, &m::DoNothing >
// ----+-------------+---------------+---------------+-----------------------+-----------------+-
>;
Use GitHub actions in addition to Travis CI.
In theory, at least, a std::tuple
should do.
After unpacking the distribution archives, the docs
directory only contains the Makefiles.
fsm.hpp
, link to latest dist, configure, make)player
with autoplay/autoeject)typed_row
examples (plain functions, lambdas, std::function
, static members...)In the examples given in fsmlite/tests/, replacing the event data type with an event-type std::shared_ptr gives the following error
fsm.h:140:106: error: call of overloaded ‘forward<const std::shared_ptr<event>&>(const std::shared_ptr<event>&)’ is ambiguous return binary_fn_helper<F, Arg1, Arg2>::invoke(forward<F>(f), forward<Arg1>(a), forward<Arg2>(b));
Hi,
Is there a way to "map" an event defined as an empty struct to a simple type such as int?
I cannot find any example or anything in the docs which describes what I want to achieve, so I explain with a couple of examples:
Using a switch works, but makes the code redundant, as any added event to the player
class (declaration and transition_table antry) would also require an switch state:
enum event_index {OPEN_CLOSE, CD_DETECTED, PLAY, PAUSE, STOP};
// Straight-forward, but a bit "clumsy"
void test_player_switch(enum event_index e)
{
player p;
switch (e)
{
case OPEN_CLOSE:
p.process_event(player::open_close());
break;
case CD_DETECTED:
p.process_event(player::open_close());
break;
case PLAY:
p.process_event(player::cd_detected{"louie, louie"});
break;
case PAUSE:
p.process_event(player::play());
break;
case STOP:
p.process_event(player::pause());
break;
default:
break
}
}
Instead of using a switch, I would like "map" an integer to en event, like this:
(note this is pseudo-code, and I am not sure it is even possible to do it that way):
// Map Event Index to their corresponding Event
const std::unordered_map<enum event_index, ??? EventType<T> ???> EventMap = {
{OPEN_CLOSE , player::open_close()},
{CD_DETECTED , player::cd_detected()},
{PLAY , player::play()},
{PAUSE , player::pause()},
{STOP , player::stop()},
};
void test_player_map(enum event_index e)
{
player p;
auto ??? event ??? = EventMap.find(e);
p.process_event(event); // How to get type-of-event ???
}
Or, if there is an undocumented way of doing this in another way, I would appreciate knowing about that.
BR,
Johan
Hello,
Is there a way to detect that a state is exited?
Thanks
Users may want to run the unit tests, but may not have autotools installed.
This may also serve a few seconds of processing time on CI build.
All supported/tested compilers should now correctly set __cplusplus
to 201103L
or higher. fsm.h
should #error
out otherwise.
As per title... or use #pragma once .
Looks like passing CXXFLAGS=-fno-exceptions
breaks configure's check for C++11 support (and rightly so).
Since reverting to <cassert>
is not an option on freestanding implementations, this wll have to be checked manually.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.