1.涉及类

ACE_Task//ACE任务
ACE_Activation_Queue//ACE命令队列

ACE_Method_Request//ACE请求(命令)

2.简介

ACE主动对象模式

主动对象模式用于降低方法执行和方法调用之间的耦合。该模式描述了另外一种更为透明的任务间通信方法。

传统上,所有的对象都是被动的代码段,对象中的代码是在对它发出方法调用的线程中执行的,当方法被调用时,调用线程将阻塞,直至调用结束。而主动对象却不一样。这些对象具有自己的命令执行线程,主动对象的方法将在自己的执行线程中执行,不会阻塞调用方法。

3.代码示例

 #include "ace/Task.h"
#include "ace/Method_Request.h"
#include "ace/Activation_Queue.h"
#include <iostream>
using namespace std; class Logger: public ACE_Task<ACE_MT_SYNCH>
{
public:
Logger() {}
int svc();
void LogMsg(const string& msg);
void LogMsgActive (const string& msg);
private:
ACE_Activation_Queue cmdQueue; //命令队列
};
class LogMsgCmd: public ACE_Method_Request
{
public:
LogMsgCmd(Logger *log,const string& msg)
{
this->log=log;
this->msg=msg;
}
virtual int call()
{
log->LogMsg(msg);
return ;
}
private:
Logger *log;
string msg;
};
void Logger::LogMsg(const string& msg)
{
cout<<msg<<endl;
}
//以主动的方式记录日志
void Logger::LogMsgActive(const string& msg)
{
//生成命令对象,插入到命令队列中
cmdQueue.enqueue(new LogMsgCmd(this,msg)); //enqueue 入队列
}
int Logger::svc()
{
while(true)
{
//遍历命令队列,执行命令(auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理)
auto_ptr<ACE_Method_Request> pMsgCmd(cmdQueue.dequeue ()); //dequeue 出队列
pMsgCmd->call();
}
return ;
}
int main (int argc, ACE_TCHAR *argv[])
{
Logger log;
log.activate(); for(int i=;i<;i++)
{
log. LogMsgActive ("hello");
ACE_OS::sleep();
log.LogMsgActive("book");
ACE_OS::sleep();
} log.wait();
return ;
}

Logger.cpp

4.结果

 $ ./tt
hello
book
hello
book
hello
book
hello
book

**************************************************************************************

高级篇:一个基于ACE的负载自适应万能线程池实现

转摘自:http://www.cppblog.com/cppx/archive/2011/02/28/140808.html#140836

**************************************************************************************

i.代码

 #include <map>
#include "ace/Task.h" // 线程状态
enum LF_Status_t
{
TH_LEADER_ACTIVE,
TH_FOLLOWER,
TH_WORKER,
TH_READY,
TH_STOP,
}; // 线程属性
struct LF_StatusTime_t
{
LF_Status_t status;
ACE_Time_Value working_tv; //线程最后一次任务的时间间隔
ACE_Time_Value start_time; //线程开始时间
ACE_Time_Value stop_time; //线程结束时间
ACE_Time_Value work_start; //线程最后一次任务的开始时间
ACE_Time_Value work_time; //截止目前线程运行总时间
}; // 线程集合
typedef std::map<ACE_thread_t,LF_StatusTime_t> LF_StatusTimeList_t; // 追随者
class LF_Follower
{
public:
LF_Follower(ACE_Thread_Mutex &leader_lock) : m_cond(leader_lock)
{
m_owner = ACE_Thread::self();
}
int wait(void){
return m_cond.wait();
}
int signal(void){
return m_cond.signal();
}
ACE_thread_t owner(void){
return m_owner;
} private:
ACE_Condition<ACE_Thread_Mutex> m_cond;
ACE_thread_t m_owner; }; // 领导者-追随者线程池 模式实现
class LeaderFollower
{
public:
LeaderFollower(void);
~LeaderFollower(void); protected:
LF_Follower * make_follower(void);//增加追随者
int become_leader(void);//自己轮岗为领导,若没有空缺,先等待
int elect_new_leader(void);//领导离任前,选举出新领导
bool leader_active(void);
void set_active_leader(ACE_thread_t leader); private:
ACE_thread_t m_current_leader;//领导者(角色转换--轮岗)
ACE_Unbounded_Queue<LF_Follower*> m_followers; //追随者们(领导者是其中的头一个)
ACE_Thread_Mutex m_followers_lock;
ACE_Thread_Mutex m_leader_lock; //////////////////////////////////////////////////////////////////////////
/// 线程池状态监控
public:
const LF_StatusTimeList_t & get_status(void) const; //现状,线程集合
const float get_load_rate(void) const; //获取的负载率 protected:
void set_status(LF_Status_t status);
void set_worktime(ACE_Time_Value work_time); private:
LF_StatusTimeList_t m_status_time_list;
ACE_Thread_Mutex m_status_lock;
};

LeaderFollower.h

 #include "LeaderFollower.h"

 //////////////////////////////////////////////////////////////////////////
LeaderFollower::LeaderFollower(void) :
m_current_leader()
{
} LeaderFollower::~LeaderFollower(void)
{
} LF_Follower *
LeaderFollower::make_follower( void )
{
ACE_GUARD_RETURN(ACE_Thread_Mutex, follower_mon, m_followers_lock, ); LF_Follower *fw;
ACE_NEW_RETURN(fw, LF_Follower(m_leader_lock), );
m_followers.enqueue_tail(fw);
//ACE_DEBUG((LM_ERROR, ACE_TEXT("(%t) make_follower \t: Now has %d followers.\n"), m_followers.size()));
return fw;
} int
LeaderFollower::become_leader( void )
{
ACE_GUARD_RETURN(ACE_Thread_Mutex, leader_mon, m_leader_lock, -); if( leader_active() && m_current_leader != ACE_Thread::self() ){
while(leader_active()){
set_status(TH_FOLLOWER);
auto_ptr<LF_Follower> fw(make_follower());
fw->wait(); // Wait until told to do so.
}
} // Mark yourself as the active leader.
set_active_leader(ACE_Thread::self());
set_status(TH_LEADER_ACTIVE);
//ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%t) become_leader \t: Becoming the leader.\n")));
return ;
} int
LeaderFollower::elect_new_leader( void )
{
ACE_GUARD_RETURN(ACE_Thread_Mutex, leader_mon, m_leader_lock, -); set_active_leader(); // Wake up a follower
if( !m_followers.is_empty() ){
ACE_GUARD_RETURN(ACE_Thread_Mutex, follower_mon, m_followers_lock, -); // Get the old follower.
LF_Follower *fw;
if( m_followers.dequeue_head(fw) != )
return -; //ACE_DEBUG((LM_ERROR, ACE_TEXT("(%t) elect_new_leader : Resigning and electing %d.\n"), fw->owner()));
return (fw->signal() == ) ? : -;
} //ACE_DEBUG((LM_ERROR, ACE_TEXT("(%t) elect_new_leader : Oops no followers left\n")));
return -;
} bool
LeaderFollower::leader_active( void )
{
return (m_current_leader != );
} void
LeaderFollower::set_active_leader( ACE_thread_t leader )
{
m_current_leader = leader;
} void LeaderFollower::set_worktime( ACE_Time_Value work_time )
{
ACE_GUARD(ACE_Thread_Mutex, status_worktime, m_status_lock);
LF_StatusTime_t & info = m_status_time_list[ACE_Thread::self()];
info.working_tv = work_time;
} void LeaderFollower::set_status( LF_Status_t status )
{
ACE_GUARD(ACE_Thread_Mutex, status_guard, m_status_lock);
LF_StatusTime_t & info = m_status_time_list[ACE_Thread::self()];
switch(status)
{
case TH_READY:
info.start_time = ACE_OS::gettimeofday();
break;
case TH_STOP:
info.stop_time = ACE_OS::gettimeofday();
break;
case TH_WORKER:
info.work_start = ACE_OS::gettimeofday();
break;
case TH_LEADER_ACTIVE:
case TH_FOLLOWER:
if( info.status == TH_WORKER )
info.work_time += ACE_OS::gettimeofday() - info.work_start;
break;
}
info.status = status;
} const LF_StatusTimeList_t &
LeaderFollower::get_status( void ) const
{
return m_status_time_list;
} const float
LeaderFollower::get_load_rate( void ) const
{
ACE_Time_Value work_time,run_time; for(LF_StatusTimeList_t::const_iterator iter = m_status_time_list.begin(); iter != m_status_time_list.end(); ++iter)
//foreach(const LF_StatusTimeList_t::value_type & info,get_status())
{
if( iter->second.status != TH_STOP ){
work_time += iter->second.work_time;
run_time += ACE_OS::gettimeofday() - iter->second.start_time;
}
}
return (float)work_time.usec()/run_time.usec()*;
}

LeaderFollower.cpp

 #include "LeaderFollower.h"

 #include "ace/Activation_Queue.h"
#include "ace/Method_Request.h" class ACE_Export LF_ThreadPool :
public ACE_Task_Base,
public LeaderFollower
{
public:
LF_ThreadPool(void);
~LF_ThreadPool(void); virtual int svc(void); int start_stread_pool( void );
int stop_thread_pool( void );
int post_request( ACE_Method_Request *request );// 任务请求接口 int get_queue_load(void){ return m_activation_queue_.method_count(); }
int get_max_thread(void){ return MaxThreadNum; }
int get_min_thread(void){ return MinThreadNum; } private:
int _fork_new_thread( void );
int _post_exit_request(void); private:
class ExitRequest : public ACE_Method_Request //内置退出请求
{
public:
virtual int call (void){
return -; // Cause exit.
}
}; bool m_bShutdown;
bool m_bRunning;
ACE_Activation_Queue m_activation_queue_; ////命令队列 static const size_t ScheduleTime = ;
static const size_t MinThreadNum = ;
static const size_t MaxThreadNum = ; };

LF_ThreadPool.h

 #include "LF_ThreadPool.h"

 LF_ThreadPool::LF_ThreadPool(void) :
m_bShutdown(false),
m_bRunning(false)
{
} LF_ThreadPool::~LF_ThreadPool(void)
{
} int LF_ThreadPool::svc( void )
{
//ACE_DEBUG((LM_ERROR, ACE_TEXT("(%t) Thread started.\t: %d working threads left.\n"),thr_count())); // 线程开始运行
m_bRunning = true; set_status(TH_READY); while(true){
// Block until this thread is the leader.
become_leader(); // 设置线程空闲时间,空闲线程将会自动退出
ACE_Time_Value tv(ScheduleTime);
tv += ACE_OS::gettimeofday(); // 从队列获取下一个请求,并获得所有权;长时间没有请求,dequeue超时返回
auto_ptr<ACE_Method_Request> request(m_activation_queue_.dequeue(&tv));
if( request.get() == NULL )
{
// 成功选择新的领导者,且工作线程数大于最少线程数-- 结束当前线程
if( elect_new_leader() == && thr_count() > MinThreadNum )
{ break; }
if( thr_count() < MinThreadNum ) // 工作线程数小于最少线程数,创建新的线程
{ _fork_new_thread();}
continue; // 继续担当领导者(优先成为领导者),或返回线程池等待
} // Elect a new leader then process the request
// 没有空余线程可成为领导者,或者线程池容量调整
if( elect_new_leader() != || thr_count() < MinThreadNum )
{
if( !m_bShutdown ) // 且没有调度关闭
if( thr_count() < MaxThreadNum ) // 未达到线程数上线
_fork_new_thread(); // 创建新的线程
} // Invoke the method request. 调用
set_status(TH_WORKER); ACE_Time_Value tv_start,tv_finish,tv_working;
tv_start = ACE_OS::gettimeofday(); int result = request->call(); // 调用 tv_finish = ACE_OS::gettimeofday();
tv_working = tv_finish - tv_start;
set_worktime(tv_working); // 任务执行耗时 // If received a ExitMethod, Notify the next Thread(if exists) to exit too.
if( result == - )
{
if( thr_count() > )
_post_exit_request();
break;
}
} // 剩下最后一个线程,线程池停止
if( thr_count() == )
m_bRunning = false; set_status(TH_STOP);
//ACE_DEBUG((LM_ERROR, ACE_TEXT("(%t) Thread stoped.\t: %d working threads left.\n"),thr_count()-1));
return ;
} int LF_ThreadPool::start_stread_pool( void )
{
m_bShutdown = false;
int iRet = activate(THR_NEW_LWP| THR_JOINABLE,MinThreadNum);
ACE_OS::sleep();//启动线程需要1秒钟,不然会出异常
return iRet;
} int LF_ThreadPool::stop_thread_pool( void )
{
// 线程池已停止
if( !m_bRunning )
return ; m_bShutdown = true;
_post_exit_request();
return wait();
} int LF_ThreadPool::post_request( ACE_Method_Request *request )
{
ACE_TRACE (ACE_TEXT ("SvcThreadPool::enqueue"));
return m_activation_queue_.enqueue (request);
} int LF_ThreadPool::_fork_new_thread( void )
{
return activate(THR_NEW_LWP| THR_JOINABLE,,);
} int LF_ThreadPool::_post_exit_request( void )
{
return post_request(new ExitRequest);
}

LF_ThreadPool.cpp

 #include <iostream>

 #include "LF_ThreadPool.h"
using std::string; class Logger
{
public:
Logger() {}
int init();
int end();
int currentNumberOfThreads(){return m_pool.thr_count();}
void LogMsg(const string& msg);//记录日志
void LogMsgActive (const string& msg);//记录日志触发
private:
LF_ThreadPool m_pool; //命令队列
}; class LogMsgCmd: public ACE_Method_Request
{
public:
LogMsgCmd(Logger *log,const string& msg)
{
this->log=log;
this->msg=msg;
}
virtual int call()
{
log->LogMsg(msg);
return ;
}
private:
Logger *log;
string msg;
};
void Logger::LogMsg(const string& msg)
{
std::cout<<ACE_Thread::self()<<" : "<<msg<<std::endl;
ACE_OS::sleep();
}
//以主动的方式记录日志
void Logger::LogMsgActive(const string& msg)
{
//生成命令对象,插入到命令队列中
m_pool.post_request(new LogMsgCmd(this,msg));
}
int Logger::init()
{
m_pool.start_stread_pool();
return ;
}
int Logger::end()
{
m_pool.stop_thread_pool();
return ;
}
int main (int argc, ACE_TCHAR *argv[])
{
ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%t) Thread main is started.\n")));
Logger log;
log.init(); for(int i=;i<;i++)
{
log.LogMsgActive ("hello");
//ACE_OS::sleep(1);
log.LogMsgActive("book");
//ACE_OS::sleep(1);
} ACE_OS::sleep();
std::cout<<"Current number of threads : "<<log.currentNumberOfThreads()<<std::endl;
log.end();
ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%t) Thread main is stoped.\n")));
return ;
}

test.cpp

ii.结果

$ ./tt
() Thread main is started.
: hello
: book
: hello
: book
: hello
: book
Current number of threads :
() Thread main is stoped.

领导者/追随者线程池模型:在一组预先分配的线程中通过“互斥”锁来同步线程之间的行为,“线程”们通过“民主选举”选出一位代表“领导者”站在最前端接收请求,拿到“任务”后,就从身后的候选“继任者”中选出一个线程代替自己作为“领导者”,自己则变成“工作者”就跑到后面默默去执行处理命令,这个“任务”是一个包含待处理数据和处理逻辑的自说明性任务,也就是说所有的线程不必事先知道怎么处理接收到的任务,因为他所拿到的“任务包”中就包含了如何处理任务的说明。就像一个“代工工厂”的工人一样,无需任何文化基础,会干活就行。

GOOD LUCK !

ACE_linux:任务 & 命令(Task and Command)的更多相关文章

  1. 深入浅出设计模式——命令模式(Command Pattern)

    模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请 ...

  2. .NET设计模式(17):命令模式(Command Pattern)(转)

    概述 在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”.但在某些场合,比如要对行为进行“记录.撤销/重做.事务”等处理,这种无法抵御变化的紧耦合是不合适的.在这种情况下,如何将“行为 ...

  3. 第 12 章 命令模式【Command Pattern】

    以下内容出自:<<24种设计模式介绍与6大设计原则>> 今天讲命令模式,这个模式从名字上看就很简单,命令嘛,老大发命令,小兵执行就是了,确实是这个意思,但是更深化了,用模式来描 ...

  4. 24种设计模式--命令模式【Command Pattern】

    今天讲命令模式,这个模式从名字上看就很简单,命令嘛,老大发命令,小兵执行就是了,确实是这个意思,但是更深化了,用模式来描述真实世界的命令情况.正在看这本书的你,我猜测分为两类:已经工作的和没有工作的, ...

  5. 设计模式14---设计模式之命令模式(Command)(行为型)

    1.场景模拟 请用软件模拟开机过程 按下启动按钮 然后电源供电 主板开始加电自检 BIOS依次寻找其他设备的BIOS并且让他们初始化自检 开始检测CPU,内存,光盘,硬盘,光驱,串口,并口,软驱即插即 ...

  6. 第14章 命令模式(Command Pattern)

    原文 第14章 命令模式(Command Pattern) 命令模式(Command Pattern) 概述   在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”.但在某些场合,比如 ...

  7. MAC 命令行工具(Command Line Tools)安装

    不过升级后安装命令行工具(Command Line Tools)时发现官网没有clt的下载安装包了,原来改了,使用命令在线安装. 打开终端,输入命令:xcode-select --install 选择 ...

  8. 设计模式--命令模式(Command)

    基本概念:  Command模式也叫命令模式 ,是行为设计模式的一种.Command模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数,命令模式将方法调用给封装起来了. 命令模式的 ...

  9. C#设计模式之十五命令模式(Command Pattern)【行为型】

    一.引言   今天我们开始讲"行为型"设计模式的第二个模式,该模式是[命令模式],又称为行动(Action)模式或交易(Transaction)模式,英文名称是:Command P ...

  10. 命令模式(Command)

    命令模式(Command) 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行.这个过程好在,三者相互 ...

随机推荐

  1. Aggregating local features for Image Retrieval

    Josef和Andrew在2003年的ICCV上发表的论文[10]中,将文档检索的方法借鉴到了视频中的对象检测中.他们首先将图像的特征描述类比成单词,并建立了基于SIFT特征的vusual word ...

  2. Android录音--AudioRecord、MediaRecorder

    Android提供了两个API用于实现录音功能:android.media.AudioRecord.android.media.MediaRecorder. 网上有很多谈论这两个类的资料.现在大致总结 ...

  3. Algernon's Noxious Emissions POJ1121 zoj1052

    One of the greatest alchemists of the lower Middle Renaissance, Algernon da Vinci (one of Leonardo's ...

  4. Call to undefined function imagettftext()解决方法

    由 老高 发表于 2014-10-03  在 代码人生 分类 老高在一个新环境中装DEDECMS的时候发现后台验证码无法显示.直接搜索一下这个错误,有人说session错误,有的说权限错误等等,这不胡 ...

  5. Webservice简单概念

    一.序言 大家或多或少都听过 WebService(Web服务),有一段时间很多计算机期刊.书籍和网站都大肆的提及和宣传WebService技术,其中不乏很多吹嘘和做广告的成 分.但是不得不承认的是W ...

  6. [改善Java代码]不同的列表选择不同的遍历方法

    一.场景: 我们来看一个场景,统计一个省的各科高考科目考试的平均分. 当然使用数据库中的一个SQL语句就能求出平均值,不过这个不再我们的考虑之列,这里只考虑使用纯Java的方式来解决.(由于我的机器配 ...

  7. Wince 中的图形编程

    图形编程程序当中,笔者主要要和大家讨论的是画刷的创建和使用以及绘图函数,比如2D图像的绘制等等. *画刷的定义: HBRUSH hBrush; *画刷的类型: 1. 系统内置画刷:GetStockOb ...

  8. centos下安装usb摄像头驱动

    centos安装在虚拟机下,win7下能正常使用摄像头. 虚拟机显示监测到摄像头,但驱动安装失败. terminal下输入yum install cheese,提示是否安装,输入y确认下载,大概100 ...

  9. 模板引擎逻辑语句处理之对单层for循环的处理

    先上代码 private function moldforExt(){//模板单层For循环处理 $SQL=$this->sql_obj; $URL=$this->url_obj; req ...

  10. unity3d游戏无法部署到windows phone8手机上的解决方法

    今天搞了个unity3d游戏,准备部署到自己的lumia 920上,数据线连接正常,操作正常,但是“build”以后,始终无法部署到手机上,也没有在选择的目录下生产任何相关文件.(你的系统必须是win ...