一、基础功能介绍

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. MySQL注射绕过技巧

    本次对以前注入的一些总结. 总有在注入的时候发现有waf或者对参数过滤了  ~~  做个文章记录下思路吧 ①.通过greatest函数绕过不能使用大小于符号的情况 我们在猜解单个字符时 通常会判断字符 ...

  2. 并查集--CSUOJ 1601 War

    并查集的经典题目: CSUOJ 1601: War Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 247  Solved: 70[Submit][Sta ...

  3. request.getScheme() 取到https正确的协议(转载)

    最近在做一个项目, 架构上使用了 Nginx +tomcat 集群, 且nginx下配置了SSL,tomcat no SSL,项目使用https协议 但是,明明是https url请求,发现 log里 ...

  4. [转]关于Java对中文排序的问题

          1 2 3 4 5 6 Comparator chinese_cmp = Collator.getInstance(Locale.CHINA);   String[] strs = new ...

  5. Markdown 简明语法手册 - 作业

    目录 Cmd Markdown 简明语法手册 1. 内容目录 2. 标签分类 3. 删除线 水平线--- 1. 斜体和粗体 2. 分级标题 标题1 标题2 标题3 3. 外链接 4. 无序列表 5. ...

  6. H2数据库使用 详解

    H2最完整的资料下载地址: http://download.csdn.net/detail/yixiaoping/5956595 H2数据库使用   H2数据库介绍 常用的开源数据库:H2,Derby ...

  7. gropf

    http://blog.csdn.net/yetyongjin/article/details/7717464 带-pg编译程序$ gcc -pg -o test test.c先运行程序$ ./tes ...

  8. unix简史及应用

    Unix 简史 1965年时,贝尔实验室(Bell Labs)加入一项由奇异电子(General Electric)和麻省理工学院(MIT)合作的计画:该计画要建立一套多使用者.多任务.多层次(mul ...

  9. SharePoint 2013 App 示例之图片墙

    应用程序实质上是 Web 应用程序.如果您知道如何生成 Web 应用程序,则您就知道如何生成 SharePoint 相关应用程序.您可以使用任何语言,如 HTML.JavaScript.PHP 或 . ...

  10. 错误 1 error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use . See online help for details.

    出现这种警告的原因是因为我们没有使用安全的字符串处理函数.如果想屏蔽这种警告,可以使用: 还可以使用其它的方法,参考: https://www.cnblogs.com/gb2013/archive/2 ...