// controlled_module_ex.hpp : controlled_module类的扩展
// 增强线程之间消息通讯
// 增加线程安全启动和安全关闭功能
// 增加定时器功能
#pragma once
#include
#include
#include "controlled_module.hpp"
struct_command
{
typedefboost::shared_ptrCCmdPtr;
unsignedintnCmd;
boost::any anyParam;
};
struct_wait_command
{
boost::any par;
unsignedintcommand;
void* event;
boost::shared_ptrresp;
};
classcontrolled_module_ex;
struct_notify
{
controlled_module_ex * sender;
intid;
boost::any par;
};
#define BM_RESERVE 1000
#define BM_RING_START BM_RESERVE+1
#define BM_RING_STOP BM_RESERVE+2
#define BM_RING_SETTIME BM_RESERVE+3
#define BM_RING_SETPARENT BM_RESERVE+4
#define BM_RING_CYCLE BM_RESERVE+5
#define BM_RING_PROCESS BM_RESERVE+6
#define BM_RING_PROCESSEND BM_RESERVE+7
#define BM_RING_PROCESSFAIL BM_RESERVE+8
#define BM_TIMER BM_RESERVE+9
#define BM_COMMAND BM_RESERVE+10
#define BM_NOTIFY BM_RESERVE+11
#define BM_USER 9000
classcontrolled_timer;
classcontrolled_module_ex:publiccontrolled_module
{
public:
controlled_module_ex()
{
m_safe =false;
}
~controlled_module_ex()
{
safestop();
}
public:
template
boolpostmessage(unsignedintnCmd,constboost::shared_ptr& p)
{
if(this==0||!m_safe)returnfalse;
boost::mutex::scoped_lock lock(m_mutex_command);
_command::CCmdPtr cmd(new_command);
cmd->nCmd = nCmd;
cmd->anyParam = p;
m_list_command.push_back(cmd);
returntrue;
}
boost::any execute(unsignedintcommand,boost::any par,inttimeout=-1)
{
boost::shared_ptrshared(new_wait_command);
_wait_command & cmd = *shared;
cmd.command = command;
cmd.event = (void*)CreateEvent(0,FALSE,FALSE,0);
cmd.par = par;
cmd.resp = boost::shared_ptr(newboost::any);
if(this->postmessage(BM_COMMAND,shared))
{
DWORDdw = WaitForSingleObject(cmd.event,timeout);
CloseHandle(cmd.event);
if(dw!=WAIT_OBJECT_0)
returnboost::any();
else
return*cmd.resp;
}
else
{
CloseHandle(cmd.event);
returnboost::any();
}
}
voidnotify(_notify p)
{
this->postmessage(BM_NOTIFY,p);
}
boolpostmessage(unsignedintnCmd,boost::any p)
{
if(this==0||!m_safe)
returnfalse;
boost::mutex::scoped_lock lock(m_mutex_command);
_command::CCmdPtr cmd(new_command);
cmd->nCmd = nCmd;
cmd->anyParam = p;
m_list_command.push_back(cmd);
returntrue;
}
boolpostmessage(unsignedintnCmd)
{
if(this==0||!m_safe)
returnfalse;
boost::mutex::scoped_lock lock(m_mutex_command);
_command::CCmdPtr cmd(new_command);
cmd->nCmd = nCmd;
cmd->anyParam = 0;
m_list_command.push_back(cmd);
returntrue;
}
virtualboolwork()
{
if(!getmessage())
returnfalse;
else
{
Sleep(this->m_sleeptime);
returntrue;
}
}
virtualvoidmessage(const_command & cmd)
{
if(cmd.nCmd==BM_RING_START)
{
this->on_safestart();
}
elseif(cmd.nCmd==BM_RING_STOP)
{
this->on_safestop();
}
elseif(cmd.nCmd==BM_TIMER)
{
this->on_timer(boost::any_cast(cmd.anyParam));
}
elseif(cmd.nCmd==BM_COMMAND)
{
boost::shared_ptrshared = boost::any_cast >(cmd.anyParam);
_wait_command & cmd = *shared;
*cmd.resp =this->on_command(cmd.command,cmd.par);
SetEvent((HANDLE)cmd.event);
}
elseif(cmd.nCmd==BM_NOTIFY)
{
try
{
_notify par = boost::any_cast(cmd.anyParam);
this->on_notify(par);
}
catch(boost::bad_any_cast)
{
}
}
}
virtualvoidrelease()
{
boost::mutex::scoped_lock lock(m_mutex_command);
m_list_command.clear();
}
voidsafestart()
{
if(!islive())
start();
m_safe =true;
m_safestart_event = (void*)CreateEvent(NULL,FALSE,FALSE,0);
postmessage(BM_RING_START);
::WaitForSingleObject((HANDLE)m_safestart_event,INFINITE);
CloseHandle(m_safestart_event);
}
voidsafestop()
{
if(this->islive())
{
m_safe =false;
m_safestop_event = (void*)CreateEvent(NULL,FALSE,FALSE,0);
{
boost::mutex::scoped_lock lock(m_mutex_command);
_command::CCmdPtr cmd(new_command);
cmd->nCmd = BM_RING_STOP;
cmd->anyParam = 0;
m_list_command.push_back(cmd);
}
DWORDdw = ::WaitForSingleObject((HANDLE)m_safestop_event,3*1000);
if(WAIT_OBJECT_0!=dw)
{
}
CloseHandle(m_safestop_event);
stop();
}
}
virtualvoidon_timer(constcontrolled_timer * p){}
virtualvoidon_safestart()
{
SetEvent(m_safestart_event);
}
virtualvoidon_safestop()
{
SetEvent(m_safestop_event);
}
virtualvoidon_notify(const_notify & p)
{
}
protected:
virtualboost::any on_command(constunsignedintcommand,constboost::any par)
{
returnboost::any();
}
boolgetmessage()
{
std::listcache;
{
boost::mutex::scoped_lock lock(m_mutex_command);
while(!m_list_command.empty())
{
_command::CCmdPtr p = m_list_command.front();
m_list_command.pop_front();
cache.push_back(p);
}
}
_command::CCmdPtr stop_command;
std::list::iterator item;
for(item = cache.begin();item!=cache.end();item++)
{
if((*(*item)).nCmd==BM_RING_STOP)
{
stop_command = *item;
break;
}
}
if(stop_command.get()==0)
{
while(!cache.empty())
{
_command::CCmdPtr p = cache.front();
cache.pop_front();
try
{
if((*p).nCmd!=BM_RING_START)
{
if(!this->m_safe)
continue;
}
this->message(*p);
}
catch(boost::bad_any_cast &)
{
}
}
returntrue;
}
else
{
cache.clear();
this->message(*stop_command);
returnfalse;
}
}
private:
void* m_safestart_event;
void* m_safestop_event;
boolm_safe;//在多线程,尤其牵涉到线程之间有类似socket级别关联时,当父线程safestop以后有可能会收到其他线程的postmessage,这时会引起线程死锁,这个m_safe就是解决这个问题的,当safestop以后不再接收新消息处理
boost::mutex m_mutex_command;
std::listm_list_command;
};
classcontrolled_timer:publiccontrolled_module_ex
{
public:
controlled_timer()
{
this->m_time = 0;
this->m_parent = 0;
this->m_step = 0;
}
~controlled_timer(){
}
protected:
controlled_module_ex* m_parent;
intm_time;
intm_step;
public:
voidstarttimer(inttime,controlled_module_ex* parent)
{
this->safestart();
this->postmessage(BM_RING_SETPARENT,parent);
this->postmessage(BM_RING_SETTIME,time);
}
voidstoptimer()
{
this->safestop();
}
public:
virtualvoidon_safestop()
{
m_time = 0;
controlled_module_ex::on_safestop();
}
virtualvoidmessage(const_command & cmd)
{
controlled_module_ex::message(cmd);
if(cmd.nCmd==BM_RING_SETTIME)
{
inttime = boost::any_cast(cmd.anyParam);
this->m_time = time/this->m_sleeptime;
this->postmessage(BM_RING_CYCLE);
}
elseif(cmd.nCmd==BM_RING_SETPARENT)
{
this->m_parent = boost::any_cast(cmd.anyParam);
}
elseif(cmd.nCmd==BM_RING_CYCLE)
{
if(m_time>0)
{
if(m_step>m_time)
{
m_parent->postmessage(BM_TIMER,this);
m_step=0;
}
m_step++;
}
this->postmessage(BM_RING_CYCLE);
}
}
};