如何知道异步状态机何时终止。 (升压::状态图)
Posted
技术标签:
【中文标题】如何知道异步状态机何时终止。 (升压::状态图)【英文标题】:How to know when an asynchronous state machine has terminated. (boost::statechart) 【发布时间】:2015-03-20 03:55:39 【问题描述】:我需要创建一个 boost::statechart::asynchronous_state_machine 并且我需要能够在外部“销毁”它。 我在文档中发现我应该调用 destroy_processor 并终止执行它。问题是这些方法只是在机器事件队列中插入一个事件,因此,如果我在处理这些事件之前删除 fifo_scheduler,则会引发错误......(参见下面的示例)
问题是......我怎么知道asynchronous_state_machine什么时候已经“终止”并且可以安全地“删除”fifo_scheduler?
#include <boost/statechart/event.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <boost/statechart/asynchronous_state_machine.hpp>
#include <boost/statechart/fifo_scheduler.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
namespace sc = boost::statechart;
// States
struct Stop;
struct Running;
struct Playing;
struct Paused;
// Events
struct EvPlay : public sc::event<EvPlay>;
struct EvStop : public sc::event<EvStop>;
struct EvPause : public sc::event<EvPause>;
// State machine and states definition
struct MyMachine : public sc::asynchronous_state_machine<MyMachine,Stop>
public:
MyMachine (my_context ctx, const unsigned int& ai_id)
: my_base(ctx)
, m_id(ai_id)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "MyMachine["<< m_id << "]: Constructor "
<< std::endl;
~MyMachine (void)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "MyMachine["<< m_id << "]: Destructor "
<< std::endl;
unsigned int id(void)const
return m_id;
private:
unsigned int m_id;
;
struct Stop : sc::state<Stop,MyMachine>
public:
typedef sc::custom_reaction<EvPlay> reactions;
Stop(my_context ctx)
: my_base(ctx)
, m_id(context<MyMachine>().id())
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnEntry["<< m_id << "]: Stop "
<< std::endl;
~Stop(void)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnExit["<< m_id << "]: Stop "
<< std::endl;
sc::result react(const EvPlay&)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "Stop::Event["<< m_id << "]: EvPlay "
<< std::endl;
return transit<Running>();
private:
unsigned int m_id;
;
struct Running : sc::state <Running, MyMachine, Playing>
public:
typedef sc::custom_reaction<EvStop> reactions;
Running(my_context ctx)
: my_base(ctx)
, m_id(context<MyMachine>().id())
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnEntry["<< m_id << "]: Running "
<< std::endl;
~Running(void)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnExit["<< m_id << "]: Running "
<< std::endl;
sc::result react(const EvStop&)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "Running::Event["<< m_id << "]: EvStop "
<< std::endl;
return transit<Stop>();
private:
unsigned int m_id;
;
struct Playing : sc::state<Playing, Running>
public:
typedef sc::custom_reaction<EvPause> reactions;
Playing(my_context ctx)
: my_base(ctx)
, m_id(context<MyMachine>().id())
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnEntry["<< m_id << "]: Playing "
<< std::endl;
~Playing(void)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnExit["<< m_id << "]: Playing "
<< std::endl;
sc::result react(const EvPause&)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "Playing::Event["<< m_id << "]: EvPause "
<< std::endl;
return transit<Paused>();
private:
unsigned int m_id;
;
struct Paused : sc::state<Paused, Running>
public:
typedef sc::custom_reaction<EvPause> reactions;
Paused(my_context ctx)
: my_base(ctx)
, m_id(context<MyMachine>().id())
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnEntry["<< m_id << "]: Paused "
<< std::endl;
~Paused(void)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "OnExit["<< m_id << "]: Paused "
<< std::endl;
sc::result react(const EvPause&)
std::cout << "th["<< boost::this_thread::get_id() << "]"
<< "Paused::Event["<< m_id << "]: EvPause "
<< std::endl;
return transit<Playing>();
private:
unsigned int m_id;
;
// ---------------------------------------------------------------------------
int main(void)
// create threadpool and ioservice
boost::thread_group threadPool;
boost::asio::io_service ioService;
// create work for ioservice
boost::asio::io_service::work* work (new boost::asio::io_service::work(ioService));
// create threads
threadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
// create machines
sc::fifo_scheduler<>* sch1(new sc::fifo_scheduler<>(true));
sc::fifo_scheduler<>::processor_handle handle1 (sch1->create_processor<MyMachine>(1));
//initiate machines
sch1->initiate_processor(handle1);
ioService.post(boost::bind(&sc::fifo_scheduler<>::operator(),sch1,0));
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
std::cout << "main_th["<< boost::this_thread::get_id() << "]:" << "destroying ... " << std::endl;
sch1->destroy_processor(handle1);
sch1->terminate();
std::cout << "main_th["<< boost::this_thread::get_id() << "]:" << " ... destroyed " << std::endl;
// some time to process the events ( not a solution ) ...
// comment this line to get the error.
boost::this_thread::sleep(boost::posix_time::milliseconds(5000));
std::cout << "main_th["<< boost::this_thread::get_id() << "]:" << "deleting ... "<< std::endl;
delete sch1;
sch1 = 0;
std::cout << "main_th["<< boost::this_thread::get_id() << "]:" << " ... deleted"<< std::endl;
// kill work to exit
delete work;
work = 0;
//wait for all threads to exit
threadPool.join_all();
return 0;
【问题讨论】:
这里完全相同的问题。在拥有 fifo_scheduler 的对象的析构函数中,我如何才能阻塞直到知道机器已经终止? 【参考方案1】:您可以通过 terminated() 函数检查 fifo_scheduler 对象内部的状态机状态。
在你的代码中你可以做
if(sch1->terminated())
// do something for the state machine has terminated
// destroy_processor() and terminate() or something else
您将使用 do 或 for 循环来解决此问题。
【讨论】:
以上是关于如何知道异步状态机何时终止。 (升压::状态图)的主要内容,如果未能解决你的问题,请参考以下文章