ACE小技巧:在ACE_Acceptor框架中,自定义服务处理器的创建
Stone Jiang
ACE_Acceptor框架使对新连接的侦听变得容易,也使创建和激活新连接的ACE_Svc_Handler的派生类变得容易。之前我们已经了解了ACE_Svc_Handle::open()挂勾函数和服务处理器
初始化时它所扮演的角色。本文我们回退几步,来了解服务处理器是如何实例化的以及我们如何自定义它的行为。
再看看ACE_Acceptor类,它是一个模板类,第一个模板参数ACE_Accetpor是代表与服务建立连接的处理器。当新的连接建立时,ACE_Acceptor调用make_svc_handler()挂勾函数来
实际创建的新建服务处理器对象。ACE_Acceptor::make_svc_handler()的实现如下:
template
<
class
SVC_HANDLE,ACE_PEER_ACCEPTOR_1
>
int
ACE_Acceptor
<
SVC_HANDLE, ACE_PEER_ACCEPTOR_2
>
::make_svc_handler(SVC_HANDLE
*&
sh)
{
ACE_TRACE (
"
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler
"
);
if
(sh
==
0
)
ACE_NEW_RETURN (sh,
SVC_HANDLER,
-
1
);
//
Set the reactor of the newly created <SVC_HANDLER> to the same
//
reactor that this <ACE_Acceptor> is using.
sh
->
reactor (
this
->
reactor ());
return
0
;
}
默认的实现包括了两步基本操作:
1. 获得一个新的SVC_HANLDER对象, 这里是使用的new运算符分配的。
2. 设置新的服务处理器的reactor指针为ACE_Accetpor使用的reactor的。
然而,如果应用程序需要通过其它方式获得SVC_HANDLER对象,而不是通过默认的构造函数那种动态分配,这又该怎么办呢?举例来说,我们可能需要:
. 从一个预分配的池中获得SVC_HANDLER对象;
. 为新创建的SVC_HANDLER传入一些额外的信息
. 使用单体的SVC_HANDLER
上面这些情形,我们都可以自定义make_svc_handler()挂勾函数来实现必要的行为。例如,假定我们新的处理器需要拥有一个处理所有对所有接收到的消息进行集中处理的中心处理
器。这个中心处理器我们用类Processor表示。我们需要每个服务处理器都拥有一个指向中心处理器的指针,而不是使Processor成为一个全局访问的指针(使用全局变量的种种弊端
本文不作详述)。我们的解决办法是: 从ACE_Accetor派生一个新类,这个新类拥有Processor的指针作成员,并且,在创建新和服务处理器(Service)的时候,把这个 Processor的
指针作参数传进去。
新的acceptor类可以这样定义:
class
My_Acceptor :
public
ACE_Acceptor
<
Service, ACE_SOCK_ACCEPTOR
>
...
{
public
:
My_Acceptor (Processor
*
processor) : processor_ (processor)
...
{ }
;
int
make_svc_handler (Service
*&
sh)
...
{
if
(sh
==
0
)
ACE_NEW_RETURN (sh,
Service (
this
->
processor_),
-
1
);
//
Set the reactor of the newly created <SVC_HANDLER> to the same
//
reactor that this <ACE_Acceptor> is using.
sh
->
reactor (
this
->
reactor ());
return
0
;
}
private
:
Processor
*
processor_;
}
就这样,现在,当My_Acceptor接受新连接的时候,make_svc_handler()挂勾函数分配一个新的处理器(Service),并把Processor*作为参数传进去。需要注意的事,尽管这里使用
的是这一个构造函数Service(Processor*)。我们仍需求为Service类定义默认的构造函数,以满足模板类ACE_Acceptor的需要。