了解hello_world boost sml状态机库

问题描述 投票:0回答:1

这里有一个 boost sml C++ 库的 hello world 示例:https://boost-ext.github.io/sml/examples.html#hello-world

// $CXX -std=c++14 hello_world.cpp
#include <boost/sml.hpp>
#include <cassert>

namespace sml = boost::sml;

namespace {
struct release {};
struct ack {};
struct fin {};
struct timeout {};

const auto is_ack_valid = [](const ack&) { return true; };
const auto is_fin_valid = [](const fin&) { return true; };

const auto send_fin = [] {};
const auto send_ack = [] {};

#if !defined(_MSC_VER)
struct hello_world {
  auto operator()() const {
    using namespace sml;
    return make_transition_table(
      *"established"_s + event<release> / send_fin = "fin wait 1"_s,
       "fin wait 1"_s + event<ack> [ is_ack_valid ] = "fin wait 2"_s,
       "fin wait 2"_s + event<fin> [ is_fin_valid ] / send_ack = "timed wait"_s,
       "timed wait"_s + event<timeout> / send_ack = X
    );
  }
};
}

int main() {
  using namespace sml;

  sm<hello_world> sm;
  static_assert(1 == sizeof(sm), "sizeof(sm) != 1b");
  assert(sm.is("established"_s));

  sm.process_event(release{});
  assert(sm.is("fin wait 1"_s));

  sm.process_event(ack{});
  assert(sm.is("fin wait 2"_s));

  sm.process_event(fin{});
  assert(sm.is("timed wait"_s));

  sm.process_event(timeout{});
  assert(sm.is(X));  // released
}
#else
class established;
class fin_wait_1;
class fin_wait_2;
class timed_wait;

struct hello_world {
  auto operator()() const {
    using namespace sml;
    return make_transition_table(
      *state<established> + event<release> / send_fin = state<fin_wait_1>,
       state<fin_wait_1> + event<ack> [ is_ack_valid ] = state<fin_wait_2>,
       state<fin_wait_2> + event<fin> [ is_fin_valid ] / send_ack = state<timed_wait>,
       state<timed_wait> + event<timeout> / send_ack = X
    );
  }
};
}

int main() {
  using namespace sml;

  sm<hello_world> sm;
  assert(sm.is(state<established>));

  sm.process_event(release{});
  assert(sm.is(state<fin_wait_1>));

  sm.process_event(ack{});
  assert(sm.is(state<fin_wait_2>));

  sm.process_event(fin{});
  assert(sm.is(state<timed_wait>));

  sm.process_event(timeout{});
  assert(sm.is(X));  // released
}
#endif

我理解

_s
创建一个带有名称的状态,并且状态上可以发生事件,这会将状态机发送到另一个状态。

让我们看看

hello_world
状态机:

struct hello_world {
  auto operator()() const {
    using namespace sml;
    return make_transition_table(
      *"established"_s + event<release> / send_fin = "fin wait 1"_s,
       "fin wait 1"_s + event<ack> [ is_ack_valid ] = "fin wait 2"_s,
       "fin wait 2"_s + event<fin> [ is_fin_valid ] / send_ack = "timed wait"_s,
       "timed wait"_s + event<timeout> / send_ack = X
    );
  }
};

如果我理解正确的话,这意味着当状态机处于状态

established
并且接收到事件
release
时,它会进入状态
fin wait 1
send_fin
是什么?
*
中的
*state<established> + event<release> / send_fin = state<fin_wait_1>
是什么?这个疯狂的语法是什么?我认为
+
/
=
只是被覆盖的运算符,可以轻松创建转换表。另外,
is_ack_valid
是什么?

我对

*
的猜测是它指定了状态机的开始状态。

事件是发生的事情。

c++ state-machine automata boost-sml
1个回答
0
投票

如果我理解正确的话,这意味着当状态机处于 状态建立并收到事件释放,它进入状态 等待 1.

正确

send_fin 是什么?

在已建立的状态下收到释放时触发的操作。它是一个在示例中完全不执行任何操作的 lambda。 :耸肩:

*state + event / send_fin = 中的*是什么 state 这个疯狂的语法是什么?我认为+、/和= 只是被覆盖的运算符,可以轻松创建 转换表。

*是初始状态,你是对的。值得注意的是,复杂的转换表实际上可以跟踪多个子机器,因此每个部分有多个 * 。

我非常怀疑你是对的,运算符重载稍微驱动了语法。说到设计,它还通过 TMP 对编译时间进行了大量优化。

另外,is_ack_valid 是什么?

事件后用方括号括起来的表达式称为守卫。即使收到事件,评估为 false 的守卫也会阻止任何操作或转换的发生。

在这个简单的例子中,lambda 总是返回 true,所以它是没有用的。一个更完整的示例实际上会检查确认上的某些内容。

我对*的猜测是它指定了状态的开始状态 机器。

正确

事件是发生的事情。

当然。它们毫无价值,它们是强类型的,并有意调度到状态机。

以下未经请求的评论。

我现在在工作中大量使用 SML。起初,这是另一件事需要学习,因为我已经在用消防水龙带喝水了。

使用了一段时间后,我想说的积极的事情是它可以非常简洁地表示复杂的流程控制,而且非常高效。

如果您有机会观看 Kris 的 2019 年 c++ now 演讲,他的 TCP 连接状态管理就是一个很好的例子,说明了这一点。

© www.soinside.com 2019 - 2024. All rights reserved.