modern
发表于 2010-1-7 13:29:46
这个说来话长,我简单的回答一下楼主的几个问题,要融会贯通的还是得看书。
1.Service configraturor可以动态配置ACE_Service_Object 、ACE_Moudle、ACE_Stream等,
注意Moudle可以配置在Stream中,也可以直接配置。
2.ACE_Service_Config是Service configraturor这套框架的控制接口。
3.ACE_Service_Repository 与 ACE_Service_Repository_Iterator 是这套框架的容器类。
4.类似make_mr ,ACE_SVC_FACTORY_DECLARE (Test_Task)
ACE_SVC_FACTORY_DEFINE (Test_Task)这种东西要是不理解的话,先看书。
5.应用程序中每次编写一个新的功能的动态库都要引入一次对应的lib库,那岂不麻烦死。
如果对这个不理解,还是先看书,理解svc.conf是怎么用的。
xtdwnuisea
发表于 2010-1-7 13:53:08
我能够理解 Service configraturor可以动态配置ACE_Service_Object ,
但我不能够理解 Service configraturor可以动态配置ACE_Moudle、ACE_Stream等...
只是因为:书上、CCM_App工程中,都没有完整的工程来讲这个事情,我不知道版主是如何学习与理解这些东西的;
在CCM_App工程中, 确实我也看到了加载ACE_Moudle、ACE_Stream, 但它们都是孤零零地被加载,不知道它如何在被加载的Stream中添加Moudle, 更不知道消息息放到Stream中后,是如何在各Moudle间运转的, 我不知道版主是否见过这样的可运行的例子,消息能运转起来的...
这个时候我要提到:我知道ACE书上是讲它可以融合二者、我也知道它DSEJ-94.pdf 94年写的论文中也是说可以加载在一起,《ACE程序员指南-网络与系统编程的实用设计模式》一书也有一句话说它们可以融合在一起,但我除了看到一个不完整的CCM_App样例工程,一个并不能运行消息,不含消息流转的工程,其它一点也看不到; 我知道书上说是可以、我的老板也说可以、您也说可以、但是事实上没有一个实际的工程,也许做程序员的人都太实际了,看不到存在的东西就认为它不存在;最后我想补充:理论上是可以的,我认可,事实上可以吗?我想问的就是这个!
modern
发表于 2010-1-7 14:55:52
他们可不是被孤零零的加载哦,
楼主没有好好看svc.conf里面的内容,
才会有上述的疑问的。
至于消息如何流转,
C++NPV2第九章上也有例子。
都是可以作为参考的。
另外不知道楼主是否看过APG的第18、19章。
那个例子或许对你会有帮助。
modern
发表于 2010-1-7 14:59:04
举例:
stream dynamic CCM_App STREAM *CCM_App:make_stream() active
{
dynamic Device_Adapter Module *CCM_App:make_da()
dynamic Event_Analyzer Module *CCM_App:make_ea()
dynamic Multicast_Router Module *CCM_App:make_mr() "-p 3001"
}
按照上述的格式,STREAM 将被加载到Service configraturor中
大括号里面的三个Module将被加载到STREAM 中。
stream dynamic CCM_App STREAM *CCM_App:make_stream() active
dynamic Device_Adapter Module *CCM_App:make_da()
dynamic Event_Analyzer Module *CCM_App:make_ea()
dynamic Multicast_Router Module *CCM_App:make_mr() "-p 3001"
这样的格式,四个模块将会分别加载到Service configraturor中。
xtdwnuisea
发表于 2010-1-7 15:19:00
楼上版主,在谈论这个问题中,您是我遇到的最务实的对话者了, 已经谈到实际问题上了;
其实我注意了svc.conf这一段了,并且做了详细测试, 我一开始也是和你一样以为svc.conf中这一段就是把三个model 加入到这个 CCM_App:make_stream 流中, 但我后来认为它不是这样的是因为,我做了如下测试 :
//这个函数中我加了我自己的代码,其目的是向这个流中添加消息, 但这个消息根本就不能在Module中流转......
MT_Stream * make_stream (void)
{
MT_Stream* pMT_Stream = new MT_Stream;
ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("make_stream - zhangcf new thread.\n")));
// WorkStreamThread* pWorkStreamThread = new WorkStreamThread( );
//pWorkStreamThread->activate();
// new thread error, exec flowing:
char p = {"333333333"};
printf("开始压入消息\n");
ACE_Message_Block * mb;
ACE_NEW_RETURN (mb, ACE_Message_Block (strlen(p)), NULL);
char* pp = (char *)mb->wr_ptr ();
mb->wr_ptr (strlen(pp));
int rval = pMT_Stream->put (mb);
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("RecordingStream::record() - ")
ACE_TEXT ("this->put() returns %d\n"),
rval));
return pMT_Stream;
}
而CCM_App例子中提供的这个函数是这样写的:
MT_Stream * make_stream (void)
{
return new MT_Stream;
}
xtdwnuisea
发表于 2010-1-7 15:20:42
CCM_App 这个项目我已经能运行起来, 我已经能把它编译成lib 并且能把 相应的
stream dynamic CCM_App STREAM *CCM_App:make_stream() active
dynamic Device_Adapter Module *CCM_App:make_da()
dynamic Event_Analyzer Module *CCM_App:make_ea()
dynamic Multicast_Router Module *CCM_App:make_mr() "-p 3001"
这些函数全部启动起来, 这些函数中的文字输出我全部都能运行起来
xtdwnuisea
发表于 2010-1-7 15:30:15
至于 消息流转,我做了Stream的单向流与双向流,真的非常熟悉; 包括流中的Module动态拆卸等, 我还做了流的压力测试与效率统计:(只能以文本方式贴出来了)
##############################
时间单位是秒(注:IBM数据是假的)
##############################
系统概况:1个单向
加入队列时间 执行完成
Windows 6 9
Linux 1.3 4.3
Linux(无屏显) 1.2 1.2
IBM 4.5 80
系统概况:2个单向
加入队列时间 执行完成
Windows 8 14
Linux 6 8
Linux(无屏显) 2 2
IBM 4.5 80
系统概况:10个单向
加入队列时间 执行完成
Windows 32 47
Linux 37 52
Linux(无屏显) 6 6
IBM 4.5 80
系统概况:20个单向
加入队列时间 执行完成
Windows 41 71
Linux 79 166
Linux(无屏显) 11 11
IBM 4.5 80
##################################
下面是针对10个单向流测试情况:
##################################
各平台1000条流消息压入测试
加入队列时间 执行完成
Windows 0.17 2.15
Linux 0.3 3
Linux(无屏显) 0.58 0.61
IBM 4.5 80
各平台10000条流消息压入测试
加入队列时间 执行完成
Windows 32 47
Linux 37 52
Linux(无屏显) 6 6
IBM 4.5 80
各平台100000条流消息压入测试(一百万)
加入队列时间 执行完成 列1
Windows 0 0 Windows估计很难出来
Linux 499 568
Linux(无屏显) 53 56
IBM 4.5 80
[ 本帖最后由 xtdwnuisea 于 2010-1-7 15:31 编辑 ]
xtdwnuisea
发表于 2010-1-7 15:38:27
还有,我想说的是svc.conf中这样加载估计是不行的, 至少于CCM_App这个例子没有做完整,因为在Stream这个章节中调度消息是要我们手工写基类调度的, 例如我们需要自己去调用put() 与get()消息,如Stream中这段代码,当然是放在基类中的,这个不是ACE基类,而是要我们自己封装的:
下面就是单向流中:作为Module之上的Task基类写法:(它的目的是调度Module间的message)
#pragma once
#include "ace/Task_T.h"
#include "ace/ace_wchar.h"
#include "Message.h"
class CBasicTask :
public ACE_Task<ACE_MT_SYNCH>
{
public:
CBasicTask(void);
~CBasicTask(void);
typedef ACE_Task<ACE_MT_SYNCH> inherited;
public:
// open (void * = 0)
int open(void* = 0 );
// Listing 101 code/ch18
int put (ACE_Message_Block *message,
ACE_Time_Value *timeout)
{
return this->putq (message, timeout);
}
// Listing 101
// Listing 1020 code/ch18
virtual int svc (void)
{
for (ACE_Message_Block *message = 0; ; )
{
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("BasicTask::svc() - ")
ACE_TEXT ("waiting for work\n" )));
if (this->getq (message) == -1)
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("getq")),
-1);
// Listing 1020
// Listing 1021 code/ch18
if (message->msg_type () == ACE_Message_Block::MB_HANGUP)
{
if (this->putq (message) == -1)
{
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("Task::svc() putq")));
message->release ();
}
break;
}
// Listing 1021
// Listing 1022 code/ch18
CMessage *recordedMessage =
(CMessage *)message->rd_ptr ();
if (this->process (recordedMessage) == -1)
{
message->release ();
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("process")),
-1);
}
// Listing 1022
// Listing 1023 code/ch18
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("BasicTask::svc() - ")
ACE_TEXT ("Continue to next stage\n" )));
if (this->next_step (message) < 0)
{
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("put_next failed")));
message->release ();
break;
}
// Listing 1023
}
return 0;
}
// Listing 103 code/ch18
virtual int close (u_long flags)
{
int rval = 0;
if (flags == 1)
{
ACE_Message_Block *hangup = new ACE_Message_Block ();
hangup->msg_type (ACE_Message_Block::MB_HANGUP);
if (this->putq (hangup) == -1)
{
hangup->release ();
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("Task::close() putq")),
-1);
}
rval = this->wait ();
}
return rval;
}
// Listing 103
// Listing 105 code/ch18
protected:
virtual int next_step (ACE_Message_Block *message_block)
{
return this->put_next (message_block);
}
// Listing 105
// Listing 104 code/ch18
virtual int process (CMessage *message) = 0;
public:
virtual int desired_threads(void);
};
modern
发表于 2010-1-7 15:45:46
很高兴看到楼主上面提出的问题,可以看出楼主确实是花了不少时间研究。
其实离楼主想要的已经越来越近了。
1.put了就会流转起来么,再我看来当然不会,put了之后,
至少放在 队列头部的Module的wirte task你得处理呀。
你不处理然后扔到队列中下一个Module的wirte task里面当然他不会流转了。
2.答复15楼的问题,
第一种方法,三个model 确实被加载到stream中,第二种方法,三个model 与一个stream被各自加载。
这不是靠推断的。我是跟代码看到源代码中确实按照我说的方式加载的。
楼主的论据有问题,导致得出了错误的结论。
xtdwnuisea
发表于 2010-1-7 16:03:14
“1.put了就会流转起来么,再我看来当然不会,put了之后,
至少放在 队列头部的Module的wirte task你得处理呀。” 刚刚看到您这句话,我就有一种乌云拔见天日的感觉, 我的问题一直就是:CCM_App这个工程是不完整的,它没有让消息流起来,所以:我没法做;
OK, 我现在就按您意思假设 make_da() make_ea() make_mr() 出来的Module是加入到make_stream() new出来的流中, 我现在再做一个测试是:
我在make_da() ...ea() ...mr() 使用的Test_Task线程中类中添加srv虚函数 其内容基本上就是我实现单向流时候的CBasicTask中的svc代码, 我做完测试再来汇报情况;