ACE中TASK架构简介及简单应用
一、基础功能介绍
1、ACE_Message_Block*,Windows消息用MSG结构表示,ACE_Task中因为不能预计各种应用中消息的类型,所以ACE_Message_Block基本上可以理解为是对一个指针的封装,这个指针指向实际的一块内存或是一个对象等等。在创建ACE_Message_Block时,可以指定是由ACE_Message_Block来管理内存(构造函数中指定一个 size_t类型的大小),还是由我们自己管理内存(构造函数中指定一个指针)。而一个ACE_Message_Block类型的指针,就是一个消息,我们通过传递它来进行逻辑的业务处理。
其包含如下两个成员变量:
/// Misc flags (e.g., DONT_DELETE and USER_FLAGS).
ACE_Message_Block::Message_Flags flags_; /// Pointer To beginning of message payload.
char *base_;
其中flags_表示数据删除标志,有效取值为DONT_DELETE。对flags_标志的作用描述如下:数据指针base_的值有两种来源,一种是由应用程序传入,在这种情况下,应该将flags_设置为DONT_DELETE,告诉框架当删除ACE_Data_Block对象时,不要删除该指针,应由应用程序自己处理;第二种是该指针由框架申请和释放,应用程序无须关注。通过这样的设计可以提高数据结构在使用上的灵活性。
2、ACE_Task::putq,事实上,到底用SendMessage还是PostMessage与ACE_Task::putq来进行类比,我很为难,PostMessage发送一个消息后立刻返回,这与通常的ACE_Task::putq行为非常类似,因为ACE_Task是运行在另外一个线程上,ACE_Task::putq只是完成将消息插入到消息队列的工作,理论上它应该立刻返回,但实际上,ACE_Task的消息队列有容量大小限制,这个限制由我们自己限定,当当前消息队列满时,ACE_Task::putq将阻塞一直到可以插入,这时候就比较类似与SendMessage,
3、ACE_Task::getq,
ACE_Message_Block * msg;
while(getq(msg) != -) // int putq (ACE_Message_Block *, ACE_Time_Value *timeout = 0);
{
// process msg here
}
4、消息处理函数,默认没有提供,svc
二、要搭架一个基于ACE_Task的消息系统,通常要做如下的步骤:
1、编写一个派生自ACE_Task的类,指定它的同步模式
ACE_Task的消息队列可以由多个处理线程共享使用,所以需要提供同步模式,例如 ACE_MT_SYNCH和ACE_NULL_SYNCH分别表示基于多线程的同步和不使用同步,这个参数是ACE_Task的一个模板参数。
其分别声明了不同的锁。
/**
* @class ACE_NULL_SYNCH
*
* @brief Implement a do nothing Synchronization wrapper that
* typedefs the @c ACE_Condition and @c ACE_Mutex to the
* @c Null* versions.
*/
class ACE_Export ACE_NULL_SYNCH
{
public:
typedef ACE_Null_Mutex MUTEX;
typedef ACE_Null_Mutex NULL_MUTEX;
typedef ACE_Null_Mutex PROCESS_MUTEX;
typedef ACE_Null_Mutex RECURSIVE_MUTEX;
typedef ACE_Null_Mutex RW_MUTEX;
typedef ACE_Null_Condition CONDITION;
typedef ACE_Null_Condition RECURSIVE_CONDITION;
typedef ACE_Null_Semaphore SEMAPHORE;
typedef ACE_Null_Mutex NULL_SEMAPHORE;
}; /**
* @class ACE_MT_SYNCH
*
* @brief Implement a default thread safe synchronization wrapper that
* typedefs the @c ACE_Condition and @c ACE_Mutex to the
* @c ACE_Condition and @c ACE_Mutex versions.
*
* @todo This should be a template, but SunC++ 4.0.1 complains about
* this.
*/
class ACE_Export ACE_MT_SYNCH
{
public:
typedef ACE_Thread_Mutex MUTEX;
typedef ACE_Null_Mutex NULL_MUTEX;
typedef ACE_Process_Mutex PROCESS_MUTEX;
typedef ACE_Recursive_Thread_Mutex RECURSIVE_MUTEX;
typedef ACE_RW_Thread_Mutex RW_MUTEX;
typedef ACE_Condition_Thread_Mutex CONDITION;
typedef ACE_Condition_Recursive_Thread_Mutex RECURSIVE_CONDITION;
typedef ACE_Thread_Semaphore SEMAPHORE;
typedef ACE_Null_Semaphore NULL_SEMAPHORE;
};
class My_Task : public ACE_Task<ACE_MT_SYNCH>
{
public:
virtual int svc();
}
2、重载 ACE_Task的 svc 方法,编写消息循环相关的代码
int My_Task::svc()
{
ACE_Message_Block * msg;
while(getq(msg) != -) // int putq (ACE_Message_Block *, ACE_Time_Value *timeout = 0);
{
// process msg here
}
}
svc 方法相当与处理线程的入口方法。
3、假设 My_Task是一个基于ACE_Task的类,创建一个唯一的My_Task实例,这个可以通过typedef ACE_Singleton<MyTask, SYNCH_METHOD> MYTASK;然后总是使用MYTASK::instance方法来获取一个My_Task的指针来完成。
4、在适当位置(一般是程序开始的时候),让My_Task开始工作
MYTASK::intance()->activate(
THR_NEW_LWP | THR_JOINABLE |THR_INHERIT_SCHED , // 线程创建的属性
n_threads = , // 线程的数目,即有多少处理线程
...)
5、在有消息发生的时候发送消息
ACE_Message_Block * msg;
// fill the msg
...
MYTASK::intance()->putq(msg);
三、简单示例
生产者消费者示例
/*************************************************************************
> File Name: task.cpp
> Author:
> Mail:
> Created Time: Tue 10 Oct 2017 02:49:52 PM CST
************************************************************************/ #include <ace/Synch.h>
#include <ace/Task.h>
#include <ace/Message_Block.h> char test_message[] = "test_message";
#define MAX_MESSAGES 10
class Counting_Test_Producer : public ACE_Task<ACE_MT_SYNCH>
{
public:
Counting_Test_Producer (ACE_Message_Queue<ACE_MT_SYNCH> *queue)
:ACE_Task<ACE_MT_SYNCH>(,queue) {}
virtual int svc (void);
}; int Counting_Test_Producer::svc (void)
{
int produced = ;
char data[] = {};
ACE_Message_Block * b = ; while()
{
ACE_OS::sprintf(data, "%s--%d.\n", test_message, produced); //创建消息块
ACE_NEW_NORETURN (b, ACE_Message_Block ());
if (b == )
{
break;
} //将data中的数据复制到消息块中
b->copy(data, );
if (produced >= MAX_MESSAGES)
{
//如果是最后一个数据,那么将数据属性设置为MB_STOP
b->msg_type(ACE_Message_Block::MB_STOP); //将消息块放入队列中
if (this->putq(b) == -)
{
b->release();
break;
}
produced ++;
ACE_DEBUG((LM_DEBUG, ACE_TEXT("Producer put the data: %s.\n"), b->base()));
break;
}
if (this->putq(b) == -)
{
b->release();
break;
}
produced ++; ACE_DEBUG((LM_DEBUG, ACE_TEXT("Producer put the data: %s.\n"), b->base()));
ACE_OS::sleep();
}
ACE_DEBUG((LM_DEBUG, ACE_TEXT("Producer done\n")));
return ;
} class Counting_Test_Consumer : public ACE_Task<ACE_MT_SYNCH>
{
public:
Counting_Test_Consumer (ACE_Message_Queue<ACE_MT_SYNCH> *queue)
:ACE_Task<ACE_MT_SYNCH> (, queue){}
virtual int svc(void);
}; int Counting_Test_Consumer::svc(void)
{
int consumer = ;
ACE_Message_Block *b = ;
ACE_DEBUG ((LM_DEBUG, ACE_TEXT("in consumer svc.\n")));
ACE_OS::sleep();
while()
{
//循环从队列中读取数据块,如果读取失败,那么退出线程
if (this->getq(b) == -)
{
break;
}
if (b->msg_type() == ACE_Message_Block::MB_STOP)
{
//如果消息属性是MB_STOP,那么表示其为最后一个数据
ACE_DEBUG((LM_DEBUG, ACE_TEXT("Consumer get the data: %s.\n"), b->base()));
ACE_DEBUG((LM_DEBUG, ACE_TEXT("Consumer get the stop msg.\n")));
b->release();
consumer++;
break;
}
ACE_DEBUG((LM_DEBUG, ACE_TEXT("Consumer get the data: %s.\n"), b->base()));
b->release();
consumer++;
ACE_OS::sleep();
} ACE_DEBUG((LM_DEBUG, ACE_TEXT("Consumer done\n")));
return ;
} int ACE_MAIN(int argc, ACE_TCHAR *argv[])
{
//创建消息队列
ACE_Message_Queue<ACE_MT_SYNCH> queue(**); // 创建生产者和消费者,它们使用同一个消息队列,只有这样才能实现线程间消息的传递
Counting_Test_Producer producer(&queue);
Counting_Test_Consumer consumer(&queue); //调用activate函数创建消费者线程
if (consumer.activate(THR_NEW_LWP | THR_DETACHED | THR_INHERIT_SCHED, ) == -)
{
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT("Consumers %p\n"), ACE_TEXT("activate")), -);
} //调用activate函数创建生产者线程
if (producer.activate ( THR_NEW_LWP | THR_DETACHED | THR_INHERIT_SCHED, ) == -)
{
ACE_ERROR((LM_ERROR, ACE_TEXT("Producers %p\n"), ACE_TEXT("activate")));
consumer.wait();
return -;
}
//调用wait函数等待线程结束
ACE_Thread_Manager::instance()->wait();
ACE_DEBUG((LM_DEBUG, ACE_TEXT("Ending test!\n")));
return ;
}

问题1:
In file included from /usr/include/ace/config-macros.h:24,
from /usr/include/ace/config-lite.h:24,
from /usr/include/ace/ACE_export.h:11,
from /usr/include/ace/Shared_Object.h:18,
from /usr/include/ace/Service_Object.h:17,
from /usr/include/ace/Task.h:17,
from task.cpp:9:
/usr/include/ace/config.h:20:2: error: #error "_FILE_OFFSET_BITS != 64"
编译时添加-D_FILE_OFFSET_BITS=64
ACE中TASK架构简介及简单应用的更多相关文章
- Android系统简介(中):系统架构
Android的系统架构栈分为4层,从上往下分别是Applications.Application framework.Libraries & Android Runtime.Linux ...
- knockout.js的简介和简单使用
1.knockout简介knockout是一个轻量级的UI类库,通过MVVM模式使JavaScript前端UI简单化knockout有四大重要概念:1)声明式绑定:使用简明移读的语法很容易地将模型(m ...
- 【转】【UML】使用Visual Studio 2010 Team System中的架构师工具(设计与建模)
Lab 1: 应用程序建模 实验目标 这个实验的目的是展示如何在Visual Studio 2010旗舰版中进行应用程序建模.团队中的架构师会通过建模确定应用程序是否满足客户的需求. 你可以创建不同级 ...
- Redis简介与简单安装
Redis简介与简单安装 一.NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类 ...
- Kafka:架构简介【转】
转:http://www.cnblogs.com/f1194361820/p/6026313.html Kafka 架构简介 Kafka是一个开源的.分布式的.可分区的.可复制的基于日志提交的发布订阅 ...
- Kafka 探险 - 架构简介
Kafka 探险 - 架构简介 这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一 ...
- C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo
在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...
- SQL SERVER 2005/2008 中关于架构的理解(一)
SQL SERVER 2005/2008 中关于架构的理解(一) 在一次的实际工作中碰到以下情况,在 SQL SERVER 2008中,新建了一个新用户去访问几张由其他用户创建的表,但是无法进行查询, ...
- SQL Server 2012中Task是如何调度的?
SQL Server 2012中Task是如何调度的?[原文来自:How It Works: SQL Server 2012 Database Engine Task Scheduling] ...
随机推荐
- python3-开发进阶Flask的基础(5)
内容概要: SQLAlchemy flsak-sqlalchemy flask-script flask-migrate Flask的目录结构 一.SQLAlchemy 1.概述 SQLAlchemy ...
- python爬取基础网页图片
python基础爬虫总结 1.爬取信息原理 与浏览器客户端类似,向网站的服务器发送一个请求,该请求一般是url,也就是网址.之后服务器响应一个html页面给客户端,当然也有其他数据类型的信息,这些就是 ...
- 【8.23校内测试】【贪心】【线段树优化DP】
$m$的数据范围看起来非常有问题??仔细多列几个例子可以发现,在$m<=5$的时候,只要找到有两行状态按位$&$起来等于$0$,就是可行方案,如果没有就不行. #include<i ...
- 03-MyBatis主从实现代码读写分离应用以及实现
建立目录结构:
- Boost汉字匹配 -- 宽字符
原文链接:http://blog.csdn.net/sptoor/article/details/4930069 思路:汉字匹配,把字符都转换成宽字符,然后再匹配. 需要用到以下和宽字符有关的类: ...
- MySQL同步状态双Yes的假象及seconds_behind_master的含义
近期由于特殊原因有一台主库宕机了一个小时没有处理,说起来这是个挺不好啥意思的事情,但是由于这个事情反而发现个比较诡异的情况,那就是在主库宕机一个小时候后,监控才发出从库IO thread中断的报警,也 ...
- Ubuntu14.04环境下配置TFTP服务器
<<<<<<<<<<<<<<<<<<<<<<<<< ...
- SEAndroid安全机制简要介绍和学习计划
与iOS相比.Android最被人诟病的是其流畅性和安全性. 然而,从4.0開始,Android不遗余力地改善其流畅性. 特别是在即将公布的L版本号中,用ART替换了Dalvik,相信会越来越流畅.至 ...
- UnsupportedOperationException:can't convert to dimension :typx=0x1
at android.content.res.TypeArray.getDimensionPixelSize(TypeArray.java:463) 今天在给项目做适配执行项目时遇到这个错误,发生错误 ...
- 卸载oracle数据库
Windows Registry Editor Version 5.00 [-HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\OracleOr ...