一概述

Streams框架是管道和过滤构架模式的一种实现,主要应用于处理数据流的系统。其实现以Task框架为基础。Task框架有两个特性非常适用于Streams框架:一是Task框架可用于创建独立线程的并发环境,这适合应用于ACE Streams框架中的主动过滤器;二是Task框架有统一的数据传输结果——消息队列,这适用于Streams框架中的管道。

二ACE_Task类

这里主要介绍与Streams框架相关的部分。

成员变量

 Task_T.h

 class ACE_Task : public ACE_Task_Base

 {

 /// Queue of messages on the ACE_Task..

   ACE_Message_Queue<ACE_SYNCH_USE, TIME_POLICY> *msg_queue_;

   /// true if should delete Message_Queue, false otherwise.

   bool delete_msg_queue_;

   /// Back-pointer to the enclosing module.

   ACE_Module<ACE_SYNCH_USE, TIME_POLICY> *mod_;

   /// Pointer to adjacent ACE_Task.

   ACE_Task<ACE_SYNCH_USE, TIME_POLICY> *next_;

 }

put函数

在ACE_Task框架中,put函数没有实际作用,在默认情况下,该函数没有执行任何操作,仅仅返回0.但是在Streams框架中,put函数与put_next函数结合起来可以实现数据在过滤器间的传输。如果put函数将数据保存在消息队列中,通过独立的线程来处理这些消息,那么它将成为一个主动过滤器;反之,如果put函数直接对数据进行处理,然后交给下一个过滤器,那么它就是一个被动过滤器。

 Task.cpp

 /// Default ACE_Task put routine.

 int

 ACE_Task_Base::put (ACE_Message_Block *, ACE_Time_Value *)

 {

   ACE_TRACE ("ACE_Task_Base::put");

   return ;

 }

put_next函数

如果在数据处理流水线有下一个过滤器,那么put_next函数用于将数据交给下一个过滤器处理。如下:

 Task_T.inl

 // Transfer msg to the next ACE_Task.

 template <ACE_SYNCH_DECL, class TIME_POLICY> ACE_INLINE int

 ACE_Task<ACE_SYNCH_USE, TIME_POLICY>::put_next (ACE_Message_Block *msg, ACE_Time_Value *tv)

 {

   ACE_TRACE ("ACE_Task<ACE_SYNCH_USE, TIME_POLICY>::put_next");

   return this->next_ ==  ? - : this->next_->put (msg, tv);

 }

next_指向的是有序过滤器的下一个过滤器。通过put_next函数,可以将数据交给下一个过滤器处理。

Streams框架应用示例

在这个示例中,我们将一个数据流的处理分为4步,在Streams框架中,将每个处理步骤称为一个Module:

  • Logrec_Reader:从文件中读取记录,然后交给下一个步骤。
  • Logrec_Timer:在记录尾部加上“format_data”
  • Logrec_Suffix:在记录尾部加上一个后缀——suffix
  • Logrec_Write:将记录显示在终端上

Logrec_Reader类

其是ACE_Task的子类,是一个主动对象类,有独立的控制线程,线程处理函数是svc。在Streams框架中,Logrec_Reader类是一个主动过滤器,代码如下:

 class Logrec_Reader : public ACE_Task<ACE_MT_SYNCH>
{
private:
ifstream fin; //标准输入流
public:
Logrec_Reader(ACE_TString logfile)
{
fin.open(logfile.c_str()); //ACE_TString.c_str() 转换为char
}
virtual int open (void *)
{
return activate();
} virtual int svc()
{
ACE_Message_Block *mblk;
int len = ;
const int LineSize = ;
char file_buf[LineSize]; while(!fin.eof())
{
fin.getline(file_buf, LineSize);
len = ACE_OS::strlen(file_buf);
ACE_NEW_RETURN(mblk, ACE_Message_Block(len + ), );
if (file_buf[len - ] == '\r')
{
len = len - ;
}
mblk->copy(file_buf, len);
// 通过put_next函数,将消息传递给下一个过滤器
put_next(mblk);
}
//构造一个MB_STOP消息
ACE_NEW_RETURN(mblk, ACE_Message_Block (, ACE_Message_Block::MB_STOP), );
put_next(mblk);
fin.close();
ACE_DEBUG((LM_DEBUG, "read svc return. \n"));
return ;
}
};

Logrec_Timer类

也是ACE_Task的子类,但是它不是主动对象类,没有创建独立线程。其实现了put函数,这个函数被它的上一个过滤器(Logrec_Reader)调用,并且数据直接在这个函数中处理。

这里for循环用于处理消息链表,在示例中并没有使用链表因此for循环只会执行一次。

 class Logrec_Timer : public ACE_Task<ACE_SYNCH>
{
private:
void format_data(ACE_Message_Block *mblk)
{
char *msg = mblk->data_block()->base();
strcat(msg, "format_data");
}
public:
virtual int put(ACE_Message_Block *mblk, ACE_Time_Value *)
{
for (ACE_Message_Block *temp = mblk;
temp != ; temp = temp->cont())
{
if (temp->msg_type() != ACE_Message_Block::MB_STOP)
{
format_data(temp);
}
}
return put_next(mblk);
}
};

Logrec_Suffix类

类似Logrec_Timer

 class Logrec_Suffix : public ACE_Task<ACE_SYNCH>
{
public:
void suffix(ACE_Message_Block *mblk)
{
char *msg = mblk->data_block()->base();
strcat(msg, "suffix\n");
}
virtual int put(ACE_Message_Block *mblk, ACE_Time_Value *)
{
for (ACE_Message_Block *temp = mblk;
temp != ; temp = temp->cont())
{
if (temp->msg_type() != ACE_Message_Block::MB_STOP)
{
suffix(temp);
}
}
return put_next(mblk);
}
};

Logrec_Write类

这里put函数由上一个过滤器(Logrec_Suffix)调用,其并没有对数据进行实际处理,只是将数据放入队列中,由线程独立处理。

 class Logrec_Write : public ACE_Task<ACE_SYNCH>
{
public:
virtual int open(void*)
{
ACE_DEBUG((LM_DEBUG, "Logrec_Writer.\n"));
return activate();
} virtual int put (ACE_Message_Block *mblk, ACE_Time_Value *to)
{
return putq(mblk, to);
} virtual int svc()
{
int stop = ;
for (ACE_Message_Block *mb; !stop && getq(mb) != -;)
{
if (mb->msg_type() == ACE_Message_Block::MB_STOP)
{
stop = ;
}
else{
ACE_DEBUG((LM_DEBUG, "%s", mb->base()));
}
put_next(mb);
}
return ;
}
};

Main

这里讲ACE_Module放入Streams中,ACE_Module才是真正数据处理的Module。ACE_Streams类有两个数据成员:stream_head_和stream_tail_,它们指向ACE_Module链表的首尾。对于每个Streams,其默认带有首尾两个Module,而后可以通过push将数据处理的Module放入执行链表中。每个Module包含两个Task,分别为读Task和写Task。在示例中仅注册了写Task,这些Module和Task通过next指针构成一个有序的串。

这里注意push有顺序要求,最后push即栈顶的为先执行的Module。

 int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
if (argc != )
{
ACE_ERROR_RETURN((LM_ERROR, "usage: %s logfile\n", argv[]), );
} ACE_TString logfile (argv[]); ACE_Stream<ACE_SYNCH> stream; ACE_Module<ACE_MT_SYNCH> *module[];
module[] = new ACE_Module<ACE_MT_SYNCH>("Reader", new Logrec_Reader(logfile), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER);
module[] = new ACE_Module<ACE_MT_SYNCH>("Formatter", new Logrec_Timer(), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER);
module[] = new ACE_Module<ACE_MT_SYNCH>("Separator", new Logrec_Suffix(), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER);
module[] = new ACE_Module<ACE_MT_SYNCH>("Writer", new Logrec_Write(), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER); for ( int i = ; i >= ; --i )
{
if (stream.push(module[i]) == -)
{
ACE_ERROR_RETURN((LM_ERROR, "push %s module into stream failed.\n", module[i]->name()), );
}
ACE_DEBUG((LM_DEBUG, "push %s module into stream success. \n", module[i]->name()));
}
ACE_Thread_Manager::instance()->wait();
}

附完整代码及结果:https://github.com/ShiningZhang/ACE_Learning/tree/master/streams

 /*************************************************************************
> File Name: logrec.cpp
> Author:
> Mail:
> Created Time: Fri 13 Oct 2017 04:19:39 PM CST
************************************************************************/
#include <fstream>
#include <ace/Synch.h>
#include <ace/Task.h>
#include <ace/Message_Block.h>
#include <ace/Stream.h>
#include "ace/Thread_Manager.h"
#include <ace/Time_Value.h>
#include <ace/Module.h> using namespace std; class Logrec_Reader : public ACE_Task<ACE_MT_SYNCH>
{
private:
ifstream fin; //标准输入流
public:
Logrec_Reader(ACE_TString logfile)
{
fin.open(logfile.c_str()); //ACE_TString.c_str() 转换为char
}
virtual int open (void *)
{
return activate();
} virtual int svc()
{
ACE_Message_Block *mblk;
int len = ;
const int LineSize = ;
char file_buf[LineSize]; while(!fin.eof())
{
fin.getline(file_buf, LineSize);
len = ACE_OS::strlen(file_buf);
ACE_NEW_RETURN(mblk, ACE_Message_Block(len + ), );
if (file_buf[len - ] == '\r')
{
len = len - ;
}
mblk->copy(file_buf, len);
// 通过put_next函数,将消息传递给下一个过滤器
put_next(mblk);
}
//构造一个MB_STOP消息
ACE_NEW_RETURN(mblk, ACE_Message_Block (, ACE_Message_Block::MB_STOP), );
put_next(mblk);
fin.close();
ACE_DEBUG((LM_DEBUG, "read svc return. \n"));
return ;
}
}; class Logrec_Timer : public ACE_Task<ACE_SYNCH>
{
private:
void format_data(ACE_Message_Block *mblk)
{
char *msg = mblk->data_block()->base();
strcat(msg, "format_data");
}
public:
virtual int put(ACE_Message_Block *mblk, ACE_Time_Value *)
{
for (ACE_Message_Block *temp = mblk;
temp != ; temp = temp->cont())
{
if (temp->msg_type() != ACE_Message_Block::MB_STOP)
{
format_data(temp);
}
}
return put_next(mblk);
}
}; class Logrec_Suffix : public ACE_Task<ACE_SYNCH>
{
public:
void suffix(ACE_Message_Block *mblk)
{
char *msg = mblk->data_block()->base();
strcat(msg, "suffix\n");
}
virtual int put(ACE_Message_Block *mblk, ACE_Time_Value *)
{
for (ACE_Message_Block *temp = mblk;
temp != ; temp = temp->cont())
{
if (temp->msg_type() != ACE_Message_Block::MB_STOP)
{
suffix(temp);
}
}
return put_next(mblk);
}
}; class Logrec_Write : public ACE_Task<ACE_SYNCH>
{
public:
virtual int open(void*)
{
ACE_DEBUG((LM_DEBUG, "Logrec_Writer.\n"));
return activate();
} virtual int put (ACE_Message_Block *mblk, ACE_Time_Value *to)
{
return putq(mblk, to);
} virtual int svc()
{
int stop = ;
for (ACE_Message_Block *mb; !stop && getq(mb) != -;)
{
if (mb->msg_type() == ACE_Message_Block::MB_STOP)
{
stop = ;
}
else{
ACE_DEBUG((LM_DEBUG, "%s", mb->base()));
}
put_next(mb);
}
return ;
}
}; int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
if (argc != )
{
ACE_ERROR_RETURN((LM_ERROR, "usage: %s logfile\n", argv[]), );
} ACE_TString logfile (argv[]); ACE_Stream<ACE_SYNCH> stream; ACE_Module<ACE_MT_SYNCH> *module[];
module[] = new ACE_Module<ACE_MT_SYNCH>("Reader", new Logrec_Reader(logfile), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER);
module[] = new ACE_Module<ACE_MT_SYNCH>("Formatter", new Logrec_Timer(), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER);
module[] = new ACE_Module<ACE_MT_SYNCH>("Separator", new Logrec_Suffix(), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER);
module[] = new ACE_Module<ACE_MT_SYNCH>("Writer", new Logrec_Write(), , , ACE_Module<ACE_SYNCH>::M_DELETE_READER); for ( int i = ; i >= ; --i )
{
if (stream.push(module[i]) == -)
{
ACE_ERROR_RETURN((LM_ERROR, "push %s module into stream failed.\n", module[i]->name()), );
}
ACE_DEBUG((LM_DEBUG, "push %s module into stream success. \n", module[i]->name()));
}
ACE_Thread_Manager::instance()->wait();
}

test:

ACE-Streams架构简介及应用的更多相关文章

  1. LoadRunner系统架构简介

    1.LoadRunner系统架构简介 LoadRunner是通过创建虚拟用户来代替真实实际用户来操作客户端软件比如Internet Explorer,来向IIS.Apache等Web服务器发送HTTP ...

  2. crtmpserver的架构简介

    crtmpserver的架构简介 一.层 Layers . 机器层 Machine layer . 操作系统层 Operating System Layer   This layer is compo ...

  3. Extjs6官方文档译文——应用架构简介(MVC,MVVM)

    应用架构简介 Extjs 同时提供对于MVC和MVVM应用架构的支持.这两个架构方式共享某些概念,而且都旨在沿着逻辑层面划分应用程序代码.每种方法在选择如何划分应用组件上都有其各自的优势. 本指南的目 ...

  4. Kafka:架构简介【转】

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

  5. LoadRunner系统架构简介与运行原理

    1.LoadRunner系统架构简介 LoadRunner是通过创建虚拟用户来代替真实实际用户来操作客户端软件比如Internet Explorer,来向IIS.Apache等Web服务器发送HTTP ...

  6. Cortex-M0(+)内核的处理器架构简介

    Cortex-M0(+)内核的处理器架构简介 2015年03月02日 16:51:12 阅读数:3158 系统架构 Cortex-M0处理器具有32位系统总线接口,以及32位地址线,即有4GB的地址空 ...

  7. 【转帖】LoadRunner系统架构简介

    LoadRunner系统架构简介: LoadRunner是通过创建虚拟用户来代替真实实际用户来操作客户端软件比如Internet Explorer,来向IIS.Apache等Web服务器发送HTTP协 ...

  8. TP 5.0 架构 简介

    TP 5.0 架构 简介 thinkphp 5.0 为API开发而设计的的高性能框架,是与以往thinkphp5.0以下版本大不相同的新型框架,病对以颠覆和重构版本,采用全新的架构思想,引入了更多的P ...

  9. ceph架构简介

    ceph架构简介 在测试OpenStack的后端存储时,看到了ceph作为后端存储时的各种优势 ,于是查询资料,总结了这篇ceph架构的博客,介绍了ceph的架构和ceph的核心组件.ceph整体十分 ...

随机推荐

  1. trie--- POJ 3764 The xor-longest Path

    The xor-longest Path Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5453   Accepted: 1 ...

  2. 某DP题目5

    题意 一个游戏里有k种装备,一开始等级为1,每打败一个怪兽,会随机掉落一件一种类型的装备,它的等级为[1,t+1]中的随机一个数,t为当前佩戴的类型的装备的等级,若掉落t+1等级的装备,就会佩戴该装备 ...

  3. Java获取Access数据库连接单例简单实例

    Java在连接Access数据库时比较方便,不用导入第三方的jar包,jdk中内置的odbc可以完成Access数据库的访问,需要注意的是,我们首先要配置Access数据库的数据源,还要区分x86和x ...

  4. PHP -- 模拟测试上传文件

    FROM :http://web.itivy.com/article-740-1.html QQ上传文件为什么那么快? “QQ上传大文件/QQ群发送大文件时,可以在极短的时间内完成”是如何做到的. 有 ...

  5. PHP生成短网地址

    思路: 1)将长网址md5生成32位签名串,分为4段, 每段8个字节; 2)对这四段循环处理, 取8个字节, 将他看成16进制串与0x3fffffff(30位1)与操作, 即超过30位的忽略处理; 3 ...

  6. URAL 1997 Those are not the droids you're looking for 二分图最大匹配

    Those are not the droids you're looking for 题目连接: http://acm.timus.ru/problem.aspx?space=1&num=1 ...

  7. myBatis 切换数据源(spring事务)理解

    1. mybatis (SqlSessionTemplate)的动态代理 a) sqlSession的结构 b)SqlSession 结构 public class SqlSessionTemplat ...

  8. 升压转换器 (Boost)

    升压转换器 (Boost) 需要将输入电压转换为较高的输出电压时,升压转换器 (Boost)是唯一的选择. 升压转换器透过内部 MOSFET 对电压充电来达成升压输出的目的,而当 MOSFET 关闭时 ...

  9. MOSFET shunt regulator substitutes for series regulator

    You would normally use a series linear regulator or a dc/dc converter to obtain 3V dc from a higher ...

  10. Oracle经典查询案例

    1.创建一个学生管理数据库,名称为student 2.最少包括一下三张表 S (SNO,SNAME)学生关系.SNO 为学号,SNAME 为姓名 C (CNO,CNAME,CTEACHER)  课程关 ...