Мне нужно создать 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;
}
Задача ещё не решена.