{"id":18,"date":"2023-12-12T08:01:00","date_gmt":"2023-12-12T07:01:00","guid":{"rendered":"https:\/\/sii.ua\/blog\/?p=18"},"modified":"2024-02-16T09:45:34","modified_gmt":"2024-02-16T08:45:34","slug":"implementing-a-state-machine-in-c17","status":"publish","type":"post","link":"https:\/\/sii.ua\/blog\/en\/implementing-a-state-machine-in-c17\/","title":{"rendered":"Implementing a State Machine in C++17"},"content":{"rendered":"\n<p>Finite State Machines are a very useful concept that allows modeling complex behavior. The basic idea is quite simple. We have a set of possible states and we define rules that govern transitions between the current state and some other state upon receiving an event. So how to implement one in C++17? Of course, there is a multitude of ways to do it. In this article, we try to explore another possibility based on several newer additions to the C++ standard.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Let\u2019s build a State Machine<\/h2>\n\n\n\n<p>So what\u2019s a state anyway? In reality, it can be anything. For the sake of this article let&#8217;s just assume that&#8217;s an arbitrary object. That object&#8217;s type can be used to distinguish it from other states. This way we don\u2019t have to maintain a separate list of all possible states (like an enumeration for example). Furthermore, we don\u2019t want to enforce any form of relationship between those types to keep them as separate as possible. So how to pass and store those completely independent types? A variadic template containing a std::tuple (both introduced in C++11) can help us with that.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate &lt;typename... States&gt;\nclass StateMachine\n{\nprivate:\nstd::tuple&lt;States...&gt; states;\n};\n<\/pre><\/div>\n\n\n<p>There are a few noteworthy things about this class. First of all, StateMachine has no prior information about the states it contains. Additionally, we don&#8217;t have to worry about their lifetime as it\u2019s tied to the lifetime of the machine itself.<\/p>\n\n\n\n<p>Next on our todo list is to keep track which state is currently selected. Normally a plain pointer or a reference would suffice, but that\u2019s not going to work in this case, because it\u2019s impossible to select a single type that would accept all possible state types (besides void*, but that would be useless for us). As we&#8217;re trying to store heterogeneous data types we can use the std::variant (C++17) for that task. Since std::variant disallows using it with references, we have to use plain pointers. Additionally, we assume that the first state type provided to the state machine is the initial state.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nstd::variant&lt;States*...&gt; currentState { &amp;std::get&lt;0&gt;(states) };\n<\/pre><\/div>\n\n\n<p>Now is time to add a method to change the current state of the machine. Once again, since we distinguish states by their type, it has to be a template method.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate &lt;typename State&gt;\nvoid transitionTo()\n{\ncurrentState = &amp;std::get&lt;State&gt;(states);\n}\n<\/pre><\/div>\n\n\n<p>So far so good. Now we need to pass event information to the machine. That raises a fundamental question &#8211; what kind of events do we want to handle? As the states are doing the actual work let\u2019s simply pass the event to the current state and let it handle it. In other words, the machine is able to accept all events that its states are capable of handling.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate &lt;typename Event&gt;\nvoid handle(const Event&amp; event)\n{\nauto passEventToState = &#x5B;&amp;event] (auto statePtr) {\nstatePtr-&gt;handle(event);\n};\nstd::visit(passEventToState, currentState);\n}\n<\/pre><\/div>\n\n\n<p>This change introduced a dependency on the type of state. Each time an event of type T is handled by the machine, the compiler ensures that all the state types have a \u2018handle\u2019 method that accepts an event of type T.<\/p>\n\n\n\n<p>The last thing that&#8217;s missing is the ability to transition to another state based on the passed event. We need to figure out how to instruct the machine to perform a transition while being inside an event handler in a given state. There are some obstacles though. We don&#8217;t want to pass the machine type to the states, because we don&#8217;t want to tie them together. To fix this issue let\u2019s return an intermediate object from the state&#8217;s &#8216;handle&#8217; method that will describe what action should the machine take.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate &lt;typename State&gt;\nstruct TransitionTo\n{\ntemplate &lt;typename Machine&gt;\nvoid execute(Machine&amp; machine)\n{\nmachine.template transitionTo&lt;State&gt;();\n}\n};\n<\/pre><\/div>\n\n\n<p>Formally speaking, after receiving an event a machine should always transition to some state, even if it\u2019s the same state as current. On the other hand, there are situations when we want to ignore an event and skip performing any action on the machine. To model this kind of behaviour we introduce a new action type.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nstruct Nothing\n{\ntemplate &lt;typename Machine&gt;\nvoid execute(Machine&amp;)\n{\n}\n};\n<\/pre><\/div>\n\n\n<p>Now we just need to plug it into our current StateMachine implementation.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate &lt;typename Event&gt;\nvoid handle(const Event&amp; event)\n{\nauto passEventToState = &#x5B;this, &amp;event] (auto statePtr) {\nstatePtr-&gt;handle(event).execute(*this);\n};\nstd::visit(passEventToState, currentState);\n}\n<\/pre><\/div>\n\n\n<p>Assuming we have some state Foo and we want to switch to state Bar on <em>Trigger<\/em> event and do nothing on <em>Ignored<\/em> event, the state\u2019s implementation could look like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nstruct Foo\n{\nTransitionTo&lt;Bar&gt; handle(const Trigger&amp; event)\n{\n\/* some important calculations etc. *\/\nreturn {};\n}\n \nNothing handle(const Ignored&amp;)\n{\nreturn {};\n}\n};\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Example<\/h2>\n\n\n\n<p>Let&#8217;s see how it all works together by implementing a simple state machine representing a door. There are two states (Closed and Open) and two events (Open, Close). This is how the transition diagram looks like:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img decoding=\"async\" width=\"390\" height=\"186\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2023\/12\/12-1.png\" alt=\"\" class=\"wp-image-55\" style=\"object-fit:cover;width:390px;height:186px\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2023\/12\/12-1.png 390w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2023\/12\/12-1-300x143.png 300w\" sizes=\"(max-width: 390px) 100vw, 390px\" \/><\/figure>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include &lt;iostream&gt;\n#include &lt;tuple&gt;\n#include &lt;variant&gt;\n#include &lt;functional&gt;\n \ntemplate &lt;typename... States&gt;\nclass StateMachine\n{\npublic:\ntemplate &lt;typename State&gt;\nvoid transitionTo()\n{\ncurrentState = &amp;std::get&lt;State&gt;(states);\n}\n \ntemplate &lt;typename Event&gt;\nvoid handle(const Event&amp; event)\n{\nauto passEventToState = &#x5B;this, &amp;event] (auto statePtr) {\nstatePtr-&gt;handle(event).execute(*this);\n};\nstd::visit(passEventToState, currentState);\n}\n \nprivate:\nstd::tuple&lt;States...&gt; states;\nstd::variant&lt;States*...&gt; currentState{ &amp;std::get&lt;0&gt;(states) };\n};\n \ntemplate &lt;typename State&gt;\nstruct TransitionTo\n{\ntemplate &lt;typename Machine&gt;\nvoid execute(Machine&amp; machine)\n{\nmachine.template transitionTo&lt;State&gt;();\n}\n};\n \nstruct Nothing\n{\ntemplate &lt;typename Machine&gt;\nvoid execute(Machine&amp;)\n{\n}\n};\n \nstruct OpenEvent\n{\n};\n \nstruct CloseEvent\n{\n};\n \nstruct ClosedState;\nstruct OpenState;\n \nstruct ClosedState\n{\nTransitionTo&lt;OpenState&gt; handle(const OpenEvent&amp;) const\n{\nstd::cout &lt;&lt; &quot;Opening the door...&quot; &lt;&lt; std::endl;\nreturn {};\n}\n \nNothing handle(const CloseEvent&amp;) const\n{\nstd::cout &lt;&lt; &quot;Cannot close. The door is already closed!&quot; &lt;&lt; std::endl;\nreturn {};\n}\n};\n \nstruct OpenState\n{\nNothing handle(const OpenEvent&amp;) const\n{\nstd::cout &lt;&lt; &quot;Cannot open. The door is already open!&quot; &lt;&lt; std::endl;\nreturn {};\n}\n \nTransitionTo&lt;ClosedState&gt; handle(const CloseEvent&amp;) const\n{\nstd::cout &lt;&lt; &quot;Closing the door...&quot; &lt;&lt; std::endl;\nreturn {};\n}\n};\n \nusing Door = StateMachine&lt;ClosedState, OpenState&gt;;\n \nint main()\n{\nDoor door;\n \ndoor.handle(OpenEvent{});\ndoor.handle(CloseEvent{});\n \ndoor.handle(CloseEvent{});\ndoor.handle(OpenEvent{});\n \nreturn 0;\n}\n<\/pre><\/div>\n\n\n<p>Above code gives us the following output:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\nOpening the door...\nClosing the door...\nCannot close. The door is already closed!\nOpening the door...\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping it all up<\/h2>\n\n\n\n<p>Of course, the above implementation is far from being complete. There are several questions that need to be answered:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>What if the states are not trivially constructible and would require passing some arguments during initialization?<\/li>\n\n\n\n<li>What if we want to decide in runtime to which state we want to transition to based on the information present in the event?<\/li>\n\n\n\n<li>Is there a way to generate a visual description of the state machine from the code itself?<\/li>\n<\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;18&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;8&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;2&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4\\\/5&quot;,&quot;size&quot;:&quot;30&quot;,&quot;title&quot;:&quot;Implementing a State Machine in C++17&quot;,&quot;width&quot;:&quot;127&quot;,&quot;_legend&quot;:&quot;{score}\\\/5&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 127px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 24px;\">\n            4\/5    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Finite State Machines are a very useful concept that allows modeling complex behavior. The basic idea is quite simple. We &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.ua\/blog\/en\/implementing-a-state-machine-in-c17\/\">Continued<\/a><\/p>\n","protected":false},"author":15,"featured_media":42,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[20,21,22,23,24],"class_list":["post-18","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-c17","tag-embedded-competency-center","tag-state-machine","tag-stdvariant","tag-templates"],"acf":[],"aioseo_notices":[],"featured_media_url":"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2023\/03\/taras-shypka-424924-unsplash-scaled.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts\/18"}],"collection":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/users\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/comments?post=18"}],"version-history":[{"count":9,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts\/18\/revisions"}],"predecessor-version":[{"id":260,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts\/18\/revisions\/260"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/media\/42"}],"wp:attachment":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/media?parent=18"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/categories?post=18"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/tags?post=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}