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_;
};