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. 20种常用的DOS命令小结

    先介绍一下通配符的概念. 通配符*和? *表示一个字符串 ?只代表一个字符 注意通配符只能通配文件名或扩展名,不能全都表示.例如我们要查找以字母y开头的所有文件,可以输入以下命令:dir y*.*:如 ...

  2. RTB实时竞价广告是未来趋势

    原文:http://www.inboundjournals.com/rtb-real-time-bidding-the-future-of-online-advertising/ [资讯图表] RTB ...

  3. #pragma_pack(n)_与___attribute(aligned(n))

    #pragma pack(n) 与 __attribute(aligned(n))   在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float等)的变量,也 ...

  4. mount: can't find cdrom in /etc /fstab or /etc/mtab

    我用的linux操作系统类别是CentOS-6.5 首先在虚拟机选项的设置里设置CD/DVD选项其中勾选Connect at power on选项 在连接中选择Use ISO image file:即 ...

  5. php 学习笔记

    //本文转自:http://www.cnblogs.com/ronghua/p/6002995.html //语法错误(syntax error)在语法分析阶段,源代码并未被执行,故不会有任何输出. ...

  6. Redux你的Angular 2应用--ngRx使用体验

    Angular2和Rx的相关知识可以看我的Angular 2.0 从0到1系列第一节:Angular 2.0 从0到1 (一)第二节:Angular 2.0 从0到1 (二)第三节:Angular 2 ...

  7. hiho欧拉路·二 --------- Fleury算法求欧拉路径

    hiho欧拉路·二 分析: 小Ho:这种简单的谜题就交给我吧! 小Hi:真的没问题么? <10分钟过去> 小Ho:啊啊啊啊啊!搞不定啊!!!骨牌数量一多就乱了. 小Hi:哎,我就知道你会遇 ...

  8. 【原创】birt 报表工具 不能运行 不能预览问题

    在windows 7以上版本中可能会遇到不能预览,或者不能再web查看器中查看 ,但是可以以html的方式查看.在网上看了好多解决方法,我试了都不可行,说明我遇到的问题不和他们的一样,这样怎么办呢? ...

  9. Entity Framework 6.1-Database First介绍

    原文:Entity Framework 6.1-Database First介绍 这种方式是比较传统的以数据库为核心的开发模式.比较适合有数据库DBA的团队.或者数据库已存在的情况. 优缺点: 1.优 ...

  10. iOS开发——毛玻璃透明

    主要实现的代码如下: self.rateInfoView是定义好的控制属性控件 可以改变透明度的值来改变毛玻璃透明的效果 // 虚拟交易费率弹窗 - (void)showRateInfo{ self. ...