C++ 从状态内的自定义函数(非操作)启动MSM调用过程_事件?

C++ 从状态内的自定义函数(非操作)启动MSM调用过程_事件?,c++,multithreading,boost,C++,Multithreading,Boost,我试图使用std::thread在用boostmsm库编码的状态机中实现并行行为。我正在使用std::thread从状态a的on\u entry方法启动线程,我想知道如何调用process\u event方法,以便从该线程内触发事件。下面是一个简单的工作示例: #include <iostream> #include <thread> #include <unistd.h> #include <boost/msm/back/state_machine.

我试图使用
std::thread
在用boostmsm库编码的状态机中实现并行行为。我正在使用
std::thread
从状态
a
on\u entry
方法启动线程,我想知道如何调用
process\u event
方法,以便从该线程内触发事件。下面是一个简单的工作示例:

#include <iostream>
#include <thread>
#include <unistd.h>

#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

// Events
struct timeout {};

struct outer_:msmf::state_machine_def<outer_> {
  struct inner_:msmf::state_machine_def<inner_> {
    template <class Event, class Fsm>
    void on_entry(Event const&, Fsm&) {
      std::cout << "[state machine entry] inner" << std::endl;
    }
    struct A:msmf::state<> {
      template <class Event, class Fsm>
      void on_entry(Event const&, Fsm& f) {
        std::cout << "[state entry] A" << std::endl;
        stop_threads_ = false;
        thread_ = new std::thread(&A::func,this);
      }
      template <class Event, class Fsm>
      void on_exit(Event const&, Fsm&) {
        stop_threads_ = true;
        thread_->join(); // wait for threads to finish
        delete thread_;
        std::cout << "[state exit] A" << std::endl;
      }
      void func() {
        while (!stop_threads_) {
          usleep(1000000);
          std::cout << "Hello" << std::endl;
          // QUESTION: how to call process_event(timeout()) here?
        }
      }
     public:
      std::thread* thread_;
      bool stop_threads_;
    };
    struct Action {
      template <class Event, class Fsm, class SourceState, class TargetState>
      void operator()(Event const&, Fsm&, SourceState&, TargetState&) {
        std::cout << "Trying again..." << std::endl;
      }
    };
    typedef A initial_state;
    struct transition_table:mpl::vector<
        msmf::Row <A,timeout,A,Action>
    > {};
  };
  typedef msm::back::state_machine<inner_> inner;
  typedef inner initial_state;
};
typedef msm::back::state_machine<outer_> outer;

void waiting_thread() {
  while(true) {
    usleep(2000000);
  }
}

int main() {
  outer sm;
  sm.start();
  std::thread wait(waiting_thread);
  wait.join();
}
#包括
#包括
#包括
#包括
#包括
#包括
名称空间msm=boost::msm;
名称空间msmf=boost::msm::front;
名称空间mpl=boost::mpl;
//事件
结构超时{};
结构外部:msmf::状态机器定义{
结构内部:msmf::状态机定义{
模板
输入时无效(事件常量和Fsm){

不幸的是,你不能那样做

以下是试图在
func()
中处理事件的代码。 这与我们的战略相似

它成功地完成了。但是我遇到了一个例外

#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>

#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

// Events
struct timeout {};

struct outer_:msmf::state_machine_def<outer_> {
  std::mutex mtx;
  typedef msm::back::state_machine<outer_> outer;
  std::weak_ptr<outer> wp;

  static std::shared_ptr<outer> create() {
    auto p = std::make_shared<outer>();
    p->wp = p; // set wp after creation.
    return p;
  }

  template <typename Ev>
  void process(Ev&& ev) {
    // process_event via backend weak_ptr
    std::lock_guard<std::mutex> g(wp.lock()->mtx);
    wp.lock()->process_event(std::forward<Ev>(ev));
  }
  struct inner_:msmf::state_machine_def<inner_> {
    std::weak_ptr<outer> wp;

    template <class Event, class Fsm>
    void on_entry(Event const&, Fsm& f) {
      std::cout << "[state machine entry] inner" << std::endl;
      wp = f.wp;
    }
    struct A:msmf::state<> {
      template <class Event, class Fsm>
      void on_entry(Event const&, Fsm& f) {
        std::cout << "[state entry] A" << std::endl;
        stop_threads_ = false;
        thread_ = new std::thread(&A::func,this, std::ref(f));
      }
      template <class Event, class Fsm>
      void on_exit(Event const&, Fsm&) {
        stop_threads_ = true;
        thread_->join(); // wait for threads to finish
        delete thread_;
        std::cout << "[state exit] A" << std::endl;
      }
      void func(inner_& f) {
        while (!stop_threads_) {
          usleep(1000000);
          std::cout << "Hello" << std::endl;
          // QUESTION: how to call process_event(timeout()) here?
          f.wp.lock()->process(timeout());
        }
      }
     public:
      std::thread* thread_;
      bool stop_threads_;
    };
    struct Action {
      template <class Event, class Fsm, class SourceState, class TargetState>
      void operator()(Event const&, Fsm&, SourceState&, TargetState&) {
        std::cout << "Trying again..." << std::endl;
      }
    };
    typedef A initial_state;
    struct transition_table:mpl::vector<
        msmf::Row <A,timeout,A,Action>
    > {};
    template <class FSM,class Event>
    void exception_caught (Event const&,FSM&,std::exception& e) {
        std::cout << e.what() << std::endl;
    }
  };
  typedef msm::back::state_machine<inner_> inner;
  typedef inner initial_state;
  template <class FSM,class Event>
  void exception_caught (Event const&,FSM&,std::exception& e) {
      std::cout << e.what() << std::endl;
  }
};

void waiting_thread() {
  while(true) {
    usleep(2000000);
  }
}

int main() {
  std::shared_ptr<outer_::outer> sm = outer_::create();
  sm->start();
  std::cout << "started" << std::endl;
  std::thread wait(waiting_thread);
  wait.join();
  std::cout << "joined" << std::endl;
}
我收到的消息是
避免了资源死锁
。它最初是由pthread库引起的。如果创建一个线程,然后从不同的线程加入该线程,则会引发异常

让我们看看代码在哪里创建线程

关键是:

      template <class Event, class Fsm>
      void on_entry(Event const&, Fsm& f) {
        std::cout << "[state entry] A" << std::endl;
        stop_threads_ = false;
        thread_ = new std::thread(&A::func,this, std::ref(f));
      }
      template <class Event, class Fsm>
      void on_exit(Event const&, Fsm&) {
        stop_threads_ = true;
        thread_->join(); // wait for threads to finish
        delete thread_;
        std::cout << "[state exit] A" << std::endl;
      }
它是从
void func(internal_&f)
中的
f.wp.lock()->进程(timeout());
调用的。func是由
thread\u=new std::thread(&A::func,this,std::ref(f));
创建的线程的入口点。 这意味着
线程->连接();
本身正在等待

这就是引发
资源死锁避免的原因

编辑

这是对该评论的回答

这不是一个完整的解决方案,但可能是设计的一个暗示

如果我拆下线程并删除
join()
,则程序会按照您的预期工作。当然
detach()
不是最佳解决方案。而且线程从未删除。您需要在产品代码中注意它们

下面代码的目的是演示状态机行为

struct A:msmf::state<> {
  template <class Event, class Fsm>
  void on_entry(Event const&, Fsm& f) {
    std::cout << "[state entry] A" << std::endl;
    stop_threads_ = false;
    thread_ = new std::thread(&A::func,this, std::ref(f));
    thread_->detach();
  }
  template <class Event, class Fsm>
  void on_exit(Event const&, Fsm&) {
    stop_threads_ = true;
    std::cout << "[state exit] A" << std::endl;
  }
  struct func {
    func(inner_& f):f(f) {}
      void operator()() {
      while (!stop_threads_) {
        usleep(1000000);
        std::cout << "Hello" << std::endl;
        // QUESTION: how to call process_event(timeout()) here?
        f.wp.lock()->process(timeout());
      }
    }
  };
 public:
  std::thread* thread_;
  bool stop_threads_;
};
结构A:msmf::状态{ 模板 输入时无效(事件常量和Fsm&f){
std::cout为了实现我想要的,接下来需要做什么工作:即拥有一个可以在并行线程中执行的函数,但也可以退出(从转换)如果需要,该函数中的状态?我更新了我的答案。更新后,代码的行为与您预期的一样。但它包括分离的线程和资源泄漏。我没有太多时间来解决它。但它指明了解决方法。为了正确连接计时器线程,您可以使用条件变量与线程线程是从主线程创建的,然后等待。在状态机的操作中,通知条件变量。然后,等待线程被解除阻止。在线程中,usleep几个持续时间,然后调用process\ U event。正如前面所述,您无法在该点直接执行。我看到的操作是使用线程安全队列并推送event对象,然后使用线程在状态机中以序列化和线程安全的顺序处理_事件。
struct A:msmf::state<> {
  template <class Event, class Fsm>
  void on_entry(Event const&, Fsm& f) {
    std::cout << "[state entry] A" << std::endl;
    stop_threads_ = false;
    thread_ = new std::thread(&A::func,this, std::ref(f));
    thread_->detach();
  }
  template <class Event, class Fsm>
  void on_exit(Event const&, Fsm&) {
    stop_threads_ = true;
    std::cout << "[state exit] A" << std::endl;
  }
  struct func {
    func(inner_& f):f(f) {}
      void operator()() {
      while (!stop_threads_) {
        usleep(1000000);
        std::cout << "Hello" << std::endl;
        // QUESTION: how to call process_event(timeout()) here?
        f.wp.lock()->process(timeout());
      }
    }
  };
 public:
  std::thread* thread_;
  bool stop_threads_;
};