【问题标题】:Understanding hello_world boost sml state machine library理解 hello_world boost sml 状态机库
【发布时间】:2021-02-15 03:17:03
【问题描述】:

这里是 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 1send_fin 是什么? *state&lt;established&gt; + event&lt;release&gt; / send_fin = state&lt;fin_wait_1&gt; 中的 * 是什么?这个疯狂的语法是什么?我认为+/= 只是简单的重写运算符,可以轻松创建转换表。还有,is_ack_valid是什么?

我对@9​​87654336@ 的猜测是它指定了状态机的开始状态。

事件是发生的事情。

【问题讨论】:

  • is_ack_valid 是验证 ack 事件的 lambda。

标签: c++ state-machine automata


【解决方案1】:

如果我理解正确的话,意思是当状态机在 状态建立并收到事件释放,它进入状态 鳍等待 1.

是的

什么是 send_fin?

在状态建立时收到释放时触发的操作。这是一个在示例中完全没有任何作用的 lambda。 :耸肩:

*state + event/send_fin = 中的 * 是什么 state 这个疯狂的语法是什么?我认为+,/和= 只是被覆盖的操作符,可以很容易地创建 转换表。

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

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

另外,is_ack_valid 是什么?

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

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

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

是的

事件是发生的事情。

当然。毫无价值,它们被强类型化并有意分派到状态机。

以下未经请求的评论。

我现在在工作中大量使用了 SML。一开始,因为我已经在用消防水龙带喝水了,所以还要学习一件事。

使用它一段时间后,我想说的积极一点是它可以非常简洁地表示复杂的流量控制,并且非常有效。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2018-04-13
    • 2015-04-21
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多