一、基础功能介绍

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架构简介及简单应用的更多相关文章

  1. Android系统简介(中):系统架构

    Android的系统架构栈分为4层,从上往下分别是Applications.Application framework.Libraries  & Android Runtime.Linux  ...

  2. knockout.js的简介和简单使用

    1.knockout简介knockout是一个轻量级的UI类库,通过MVVM模式使JavaScript前端UI简单化knockout有四大重要概念:1)声明式绑定:使用简明移读的语法很容易地将模型(m ...

  3. 【转】【UML】使用Visual Studio 2010 Team System中的架构师工具(设计与建模)

    Lab 1: 应用程序建模 实验目标 这个实验的目的是展示如何在Visual Studio 2010旗舰版中进行应用程序建模.团队中的架构师会通过建模确定应用程序是否满足客户的需求. 你可以创建不同级 ...

  4. Redis简介与简单安装

    Redis简介与简单安装   一.NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类 ...

  5. Kafka:架构简介【转】

    转:http://www.cnblogs.com/f1194361820/p/6026313.html Kafka 架构简介 Kafka是一个开源的.分布式的.可分区的.可复制的基于日志提交的发布订阅 ...

  6. Kafka 探险 - 架构简介

    Kafka 探险 - 架构简介 这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一 ...

  7. C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo

    在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...

  8. SQL SERVER 2005/2008 中关于架构的理解(一)

    SQL SERVER 2005/2008 中关于架构的理解(一) 在一次的实际工作中碰到以下情况,在 SQL SERVER 2008中,新建了一个新用户去访问几张由其他用户创建的表,但是无法进行查询, ...

  9. SQL Server 2012中Task是如何调度的?

    SQL Server 2012中Task是如何调度的?[原文来自:How It Works: SQL Server 2012 Database Engine Task Scheduling]     ...

随机推荐

  1. python实现图片验证码

    1 验证基础知识1.1 Python生成随机验证码,需要使用PIL模块. # 安装 pip3 install pillow 1.2 创建图片 from PIL import Image img = I ...

  2. Spring Mvc 前台数据的获取、SpringMvc 表单数据的获取

    首先在web.xml 里面配置一个编码过滤器 <!-- springmvc框架本身没有处理请求编码,我们自己配置一个请求编码过滤器 --> <filter> <filte ...

  3. VK Cup 2016 - Qualification Round 2 B. Making Genome in Berland 水题

    B. Making Genome in Berland 题目连接: http://www.codeforces.com/contest/638/problem/B Description Berlan ...

  4. Codeforces Round #301 (Div. 2) C. Ice Cave BFS

    C. Ice Cave Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/540/problem/C ...

  5. jQuery使用一知半解

    jQuery是目前使用最广泛的javascript函数库.据统计,全世界排名前100万的网站,有46%使用jQuery,远远超过其他库.微软公司甚至把jQuery作为他们的官方库.对于网页开发者来说, ...

  6. CMSIS-SVD Schema File Ver. 1.0

    <?xml version="1.0" encoding="UTF-8"?> <!-- date: 07.12.2011 Copyright ...

  7. Spring EL运算符实例

    Spring EL支持大多数标准的数学,逻辑和关系运算符. 例如, 关系运算符 – 等于 (==, eq), 不等于 (!=, ne), 小于 (<, lt), 小于或等于 (<= , l ...

  8. 使用JS在客户端判断当前网络状态

    1. navigator.onLine 2. ajax请求 3. 获取网络资源 1. navigator.onLine 通过navigator.onLine判断当前网络状态: 12345 if(nav ...

  9. MONO,原来你是水中月

    什么是MONO? MONO项目是由Ximian发起的,由Miguel de lcaza领导的,一个致力于开创.NET在Linux上使用的开源工程.它包含了一个C#语言的编译器,一个CLR的运行时,和一 ...

  10. 如何编译Linux内核

    内核,是一个操作系统的核心.它负责管理系统的进程.内存.设备驱动程序.文件和网络系统,决定着系统的性能和稳定性.Linux作为一个自由软件,在广 大爱好者的支持下,内核版本不断更新.新的内核修订了旧内 ...