如何知道异步状态机何时终止。 (升压::状态图)

时间:2015-01-21 15:09:37

标签: c++ asynchronous boost boost-statechart

我需要创建一个boost :: statechart :: asynchronous_state_machine,我需要能够" destroy"在外面。 我在文档中发现我应该调用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;
}

1 个答案:

答案 0 :(得分:0)

您可以通过 terminate() 函数检查 fifo_scheduler 对象内部状态机的状态。

在你的代码中你可以做到

if(sch1->terminated()) {
    // do something for the state machine has terminated
    // destroy_processor() and terminate() or something else
}

您将使用 do 或 for cycle 来处理这种原因。