boost deadline_timer 编译问题

boost deadline_timer compile issue

以下源代码无法使用 MSVC 12 进行编译。

IMCThreadMngr.cpp

#include "IMCThreadMngr.h"


CIMCThreadMngr::CIMCThreadMngr() : mService(),
mWork(mService)
{}

CIMCThreadMngr::~CIMCThreadMngr() {};


void CIMCThreadMngr::StopManager()
{
    std::cout << "Manager ceasing" << std::endl;
    mService.stop();
    mServicethread.join();
    std::cout << "Manager ceased" << std::endl;
}

void CIMCThreadMngr::StartManager()
{
    mServicethread = boost::thread(boost::bind(&boost::asio::io_service::run, &mService));
}

void CIMCThreadMngr::RegisterThread(const std::string& name, int timeout)
{
    if (name.length() == 0) {
        std::cout << "No thread name provided" << std::endl;
        return;
    }
    boost::mutex::scoped_lock lock(mGroupMutex);

    ThreadObject ob = ThreadObject(mService);   
    ob.name_ = name;
    if (timeout > 0) {
    ob.timeout_ = timeout;
    }
    else {
    ob.timeout_ = 2000;
    }
    mThreadGroup.push_back(ob);

}

void CIMCThreadMngr::UnRegisterThread(const std::string& name)
{
    if (name.length() == 0) {
        std::cout << "No thread name provided" << std::endl;
        return;
    }

    boost::mutex::scoped_lock lock(mGroupMutex);

    std::vector<ThreadObject>::iterator obref;
    if (FindThreadObject(name, obref)){
        mThreadGroup.erase(obref);
    }
}

void CIMCThreadMngr::ThreadCheckIn(const std::string& name){

    if (name.length() == 0) {
        std::cout << "No thread name provided" << std::endl;
        return;
    }

    boost::mutex::scoped_lock lock(mGroupMutex);

    std::vector<ThreadObject>::iterator obref;  
    if (FindThreadObject(name, obref)){
        obref->timer_.cancel();
        obref->timer_.expires_from_now(boost::posix_time::seconds(obref->timeout_));
        obref->timer_.async_wait(boost::bind(&CIMCThreadMngr::TimeoutElapsed, this));
    }
}

bool CIMCThreadMngr::FindThreadObject(const std::string name, std::vector<ThreadObject>::iterator& ob){

    for (ob = mThreadGroup.begin(); ob != mThreadGroup.end(); ob++) {
        if ((ob->name_.compare(name) == 0)) {
            return true;
        }
    }
    return false;
}

void CIMCThreadMngr::TimeoutElapsed(const boost::system::error_code& e, const std::string& name){

    boost::mutex::scoped_lock lock(mGroupMutex);

    if (e != boost::asio::error::operation_aborted)
    {
        std::cout << "Thread " << name << " did has not responded" << std::endl; // Timer was not cancelled, take necessary action.
        ThreadCheckIn(name);
    }
}

IMCThreadMngr.h

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/mutex.hpp>
#include <vector>


class CIMCThreadMngr {

public:

    struct ThreadObject {

        std::string name_;
        int timeout_;
        bool threadrunning_;
        boost::posix_time::ptime lastupdate_;
        boost::asio::deadline_timer timer_;

        ThreadObject(boost::asio::io_service& service) : timer_(service)
        {
            timer_.expires_from_now(boost::posix_time::millisec(3000));
        }

    };

public:
    CIMCThreadMngr();
    ~CIMCThreadMngr();

    void StopManager();
    void StartManager();

    void RegisterThread(const std::string& name, int timeout);
    void UnRegisterThread(const std::string& name);
    void ThreadCheckIn(const std::string& name);
    bool FindThreadObject(const std::string name, std::vector<ThreadObject>::iterator& ob);
    void TimeoutElapsed(const boost::system::error_code& e, const std::string& name);   
    void TimeoutElapsed( );

private:

    boost::asio::io_service mService;
    boost::asio::io_service::work mWork;
    boost::thread mServicethread;
    std::vector<ThreadObject> mThreadGroup;
    boost::mutex mGroupMutex;

};

我运行遇到的编译器问题如下

f:\boost\boost_1_57_0\boost\asio\basic_deadline_timer.hpp(510): error C2248: 'boost::asio::basic_io_object<TimerService,false>::operator =' : cannot access private member declared in class 'boost::asio::basic_io_object<TimerService,false>'
          with
          [
              TimerService=boost::asio::deadline_timer_service<boost::posix_time::ptime,boost::asio::time_traits<boost::posix_time::ptime>>
          ]
          f:\boost\boost_1_57_0\boost\asio\basic_io_object.hpp(164) : see declaration of 'boost::asio::basic_io_object<TimerService,false>::operator ='
          with
          [
              TimerService=boost::asio::deadline_timer_service<boost::posix_time::ptime,boost::asio::time_traits<boost::posix_time::ptime>>
          ]
          This diagnostic occurred in the compiler generated function 'boost::asio::basic_deadline_timer<boost::posix_time::ptime,boost::asio::time_traits<boost::posix_time::ptime>,boost::asio::deadline_timer_service<Time,TimeTraits>> &boost::asio::basic_deadline_timer<Time,TimeTraits,boost::asio::deadline_timer_service<Time,TimeTraits>>::operator =(const boost::asio::basic_deadline_timer<Time,TimeTraits,boost::asio::deadline_timer_service<Time,TimeTraits>> &)'
          with
         [
             Time=boost::posix_time::ptime,            TimeTraits=boost::asio::time_traits<boost::posix_time::ptime>
         ]

希望这个问题是相当简单的,尽管我在上面的代码和 deadline_timer.

的提升示例之间找不到明显的区别

boost::asio::deadline_timer 既不可复制也不可移动(既不可复制也不可移动)。结果,CIMCThreadMgr::ThreadObject 也不是,这意味着您不能有 std::vector<ThreadObject>.

解决此问题的一个简单方法是将 deadline_timer 保持在 shared_ptr 中,如

struct ThreadObject {
    std::string name_;
    int timeout_;
    bool threadrunning_;
    boost::posix_time::ptime lastupdate_;

    // HERE
    std::shared_ptr<boost::asio::deadline_timer> timer_;

    ThreadObject(boost::asio::io_service& service)
      // Also HERE
      : timer_(std::make_shared<boost::asio::deadline_timer>(service))
    {
        // -> instead of . now.
        timer_->expires_from_now(boost::posix_time::millisec(3000));
    }
};

如果你走这条路,你还必须将 . 替换为 ->,其中 timer_ 被使用:

if (FindThreadObject(name, obref)){
    //           vv-- HERE
    obref->timer_->cancel();
    obref->timer_->expires_from_now(boost::posix_time::seconds(obref->timeout_));
    obref->timer_->async_wait(boost::bind(&CIMCThreadMngr::TimeoutElapsed, this));
}

可能可以使用 std::unique_ptr,但这可能需要对代码进行更大的更改,而不是在一些地方将 . 替换为 ->(因为 ThreadObject 只能移动但不能复制)。