Следующий источник не будет компилироваться с использованием 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
будет только подвижным, но не копируемым).