Created
August 14, 2018 01:58
-
-
Save indiosmo/08ab24181770125d5a2448d27f6ae99f to your computer and use it in GitHub Desktop.
SML - Hierarchical Machine
This file contains 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
struct client_protocol | |
{ | |
// clang-format off | |
// public interface | |
struct ev_connect{}; | |
struct ev_disconnect{}; | |
// connection handlers | |
struct ev_error{}; | |
struct ev_connected{}; | |
struct ev_handshake_ack{}; | |
struct ev_disconnected {}; | |
struct ev_fin {}; | |
// stream handlers | |
struct ev_retry{}; | |
struct ev_payload | |
{ | |
const_buffer data; | |
}; | |
// clang-format on | |
struct events | |
{ | |
std::function<void()> established; | |
std::function<void()> disconnected; | |
std::function<void()> error; | |
std::function<void(const_buffer)> payload; | |
}; | |
struct actions | |
{ | |
std::function<void()> connect; | |
std::function<void(bool initiator)> disconnect; | |
std::function<void()> start_stream; | |
std::function<void()> send_handshake; | |
std::function<void()> wait_retry; | |
}; | |
struct connected | |
{ | |
auto operator()() | |
{ | |
using namespace boost::sml; | |
namespace sml = boost::sml; | |
// clang-format off | |
return make_transition_table( | |
*"handshake"_s + sml::on_entry<_> / [](actions& ac) { ac.start_stream(); ac.send_handshake(); } | |
,"handshake"_s + sml::event<ev_handshake_ack> = "established"_s | |
,"established"_s + sml::on_entry<_> / [](events& ev){ ev.established(); } | |
,"established"_s + sml::event<ev_payload> / [](events& ev, const ev_payload& e) { | |
ev.payload(e.data); | |
} | |
); | |
// clang-format on | |
} | |
}; | |
struct protocol | |
{ | |
auto operator()() | |
{ | |
using namespace boost::sml; | |
namespace sml = boost::sml; | |
// clang-format off | |
return make_transition_table( | |
*"disconnected"_s + sml::event<ev_connect> = "connecting"_s | |
,"connecting"_s + sml::on_entry<_> / [](actions& ac) { ac.connect(); } | |
,"connecting"_s + sml::event<ev_connected> = state<connected> | |
,"connecting"_s + sml::event<ev_disconnect> = "disconnecting"_s | |
,state<connected> + sml::on_exit<_> / [](events& ev) { ev.disconnected(); } | |
,state<connected> + sml::event<ev_disconnect> = "disconnecting"_s | |
,state<connected> + sml::event<ev_retry> = "waiting_retry"_s | |
,state<connected> + sml::event<ev_fin> = "fin"_s | |
,state<connected> + sml::event<ev_error> / [](actions& ac, events& ev) | |
{ | |
ac.disconnect(false); | |
ev.error(); | |
} = X | |
,"disconnecting"_s + sml::on_entry<_> / [](actions& ac) { ac.disconnect(true); } | |
,"disconnecting"_s + sml::event<ev_disconnected> = "disconnected"_s | |
,"waiting_retry"_s + sml::on_entry<_> / [](actions& ac) { ac.wait_retry(); } | |
,"waiting_retry"_s + sml::event<ev_connect> = "connecting"_s | |
,"waiting_retry"_s + sml::event<ev_disconnect> = "disconnecting"_s | |
,"fin"_s + sml::on_entry<_> / [](actions& ac) { ac.disconnect(false); } | |
); | |
// clang-format on | |
} | |
}; | |
auto operator()() | |
{ | |
using namespace boost::sml; | |
namespace sml = boost::sml; | |
// clang-format off | |
return make_transition_table( | |
*state<protocol> + sml::event<ev_error> / [](actions& ac, events& ev) | |
{ | |
ac.disconnect(false); | |
ev.error(); | |
} = X | |
); | |
// clang-format on | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment