如何删除boost io_service

时间:2016-10-16 00:08:04

标签: c++ boost

我的简化问题
我读了this thread,我试图删除io_service对象。我这样做

m_IO.stop();
m_IO.~io_service();

m_IO是boost::asio::io_service的对象。我发现我的帖子被m_IO.~io_service();屏蔽了。如何删除io_service

我的完整问题
我通过使用boost io_service和截止时间计时器来制作每日计时器。问题是当我想删除我的日常计时器时,我的线程会在尝试删除boost io_service时消失。

main.cpp

int main()
{
    myDailyTimer* pTimer = new myDailyTimer;
    // do something
    delete pTimer;
    return 0;
}

我在myDailyTimer.cpp::int i = 0;myDailyTimer.cpp::int j = 0;main::return 0;设置了分数点我的主线程可以达到int i = 0;,我的计时器线程无法到达int j = 0;,我的主线程无法到达return 0;

我发现我的主线程在尝试删除boost::asio::io_service对象时会消失。如何解决这个问题呢?我是以错误的方式使用boost::asio::io_service吗?

myDailyTimer.h

class myDailyTimerInterface
{
public:
    myDailyTimerInterface(){}
    ~myDailyTimerInterface(){}

    virtual void TimerCallback(int nTimerID) = 0;
};
class myDailyTimer :
    public myThread
{
public:
    boost::asio::io_service m_IO;
    boost::asio::deadline_timer * m_pTimer;
    tm m_tmSpecificTime;
    std::string m_strSpecificTime;
    int m_nTimerID;
    myDailyTimerInterface* m_pParent;
public:
    myDailyTimer();
    ~myDailyTimer();

    void SetTime(tm strIN, int nID); // msec
    void TimerCallback();

    //Override
    void ThreadMain();
protected:
    std::string MakeStringSpecificTime();
    void AddOneDay();
};


myDailyTimer.cpp

myDailyTimer::myDailyTimer()
{
    m_pTimer = 0;
    m_strSpecificTime = "";
}

myDailyTimer::~myDailyTimer()
{
    EndThread();
    if (m_pTimer != 0)
    {
        m_pTimer->cancel();
        delete m_pTimer;
    }
    m_IO.stop();
    m_IO.~io_service();
    int i = 0;
    i++;
}

void myDailyTimer::SetTime(tm tmIN, int nID) // msec
{
    if (m_pTimer != 0)
    {
        m_pTimer->cancel();
        delete m_pTimer;
    }
    m_tmSpecificTime = tmIN;
    m_strSpecificTime = MakeStringSpecificTime();
    m_nTimerID = nID;
    m_pTimer = new boost::asio::deadline_timer(m_IO, boost::posix_time::time_from_string(m_strSpecificTime));
    m_pTimer->async_wait(boost::bind(&myDailyTimer::TimerCallback, this));

    myThread::Start();
}

std::string myDailyTimer::MakeStringSpecificTime()
{
    time_t localTime;
    localTime = mktime(&m_tmSpecificTime); // time is GMT local
    struct tm * ptm = gmtime(&localTime); // convert time to GMT +0
    char veccNextTime[64];
    memset(veccNextTime, 0, sizeof(veccNextTime));
    sprintf(veccNextTime, "%d-%02d-%02d %02d:%02d:%02d.000",
        ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
        ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    std::string strTemp(veccNextTime);
    return strTemp;
}

void myDailyTimer::AddOneDay()
{
    m_tmSpecificTime.tm_mday += 1;
    mktime(&m_tmSpecificTime); /* normalize result */
}

void myDailyTimer::TimerCallback()
{
    if (m_pParent != 0)
        m_pParent->TimerCallback(m_nTimerID);
    //m_timer->expires_from_now(boost::posix_time::milliseconds(m_nTimerDuration));
    AddOneDay();
    m_strSpecificTime = MakeStringSpecificTime();
    m_pTimer->expires_at(boost::posix_time::time_from_string(m_strSpecificTime));
    m_pTimer->async_wait(boost::bind(&myDailyTimer::TimerCallback, this));
}

//Override
void myDailyTimer::ThreadMain()
{
    while (!IsEndThread())
        m_IO.run();
    int j = 0;
    j++;
}


1 个答案:

答案 0 :(得分:1)

正如DanMašek所提到的,明确地调用析构函数并不是一个好的模式。停止io_service的标准方法是停止待处理的每个“工作”,然后等待io_service::run函数返回。另外,为了防止io_service::run函数过早返回,最好创建一个io_service::work对象的实例。

希望您能够将此示例修改为您的用例:

namespace asio = boost::asio;

class MyTimer {
    using Clock = std::chrono::steady_clock;

  public:
    MyTimer(Clock::duration duration) 
      : _work(_ios)
      , _timer(_ios)
      , _thread([this] { _ios.run(); })
    {
      _ios.post([this, duration] { start(duration); });
    }

    ~MyTimer() {
      _ios.post([this] { stop(); });
      _thread.join();
    }

  private:
    void start(Clock::duration duration) {
      _timer.expires_from_now(duration);
      _timer.async_wait([this](boost::system::error_code) {
          // NOTE: Be careful here as this is run from inside
          //       the thread.
          if (!_work) {
            // Already stopped.
            std::cout << "Stopped" << std::endl;
            return;
          }
          std::cout << "Timer fired" << std::endl;
        });
    }

    void stop() {
      _work.reset();
      _timer.cancel();
    }

  private:
    asio::io_service _ios;
    boost::optional<asio::io_service::work> _work;
    asio::steady_timer _timer;
    std::thread _thread;
};

int main() {
  auto* my_timer = new MyTimer(std::chrono::seconds(1));
  delete my_timer;
  return 0;
}