贝贝花花包包店,精品555皮具,钱夹,皮夹

字体: | 推荐给好友 上一篇 | 下一篇

ACE程序员教程-第6章 事件多路分离和分派的体系结构模式

发布: 2008-6-13 14:22 | 作者: Umar Syyid | 来源: 转载 | 查看: 287次

 

6.2.2.1 从反应堆内部分派表中隐式拆除事件处理器

  隐式拆除是更为常用的从反应堆中拆除事件处理器的技术。事件处理器的每个“handle_”方法都会返回一个整数给反应堆。如果此整数为0,在处理器方法完成后、事件处理器将保持在反应堆上的登记。但是,如果“handle_”方法返回的整数<0,反应堆将自动回调此事件处理器的handle_close()方法,并将它从自己的内部分派表中拆除。handle_close()方法用于执行处理器特有的任何清除工作,它们需要在事件处理器被拆除前完成;其中可以包括像删除处理器申请的动态内存、或关闭日志文件这样的工作。

  在上面所描述的例子中,必须将事件处理器从内存中实际清除。这样的清除也可以发生在具体事件处理器类的handle_close()方法中。设想下面的具体事件处理器:

 

class MyEventHandler: public ACE_Event_Handler

{

public:

MyEventHandler(){//construct internal data members}

 

virtual int

handle_close(ACE_HANDLE handle, ACE_Reactor_Mask mask)

{

delete this; //commit suicide

}

 

~MyEventHandler(){//destroy internal data members}

 

private:

//internal data members

}

 

在从反应堆注销、以及handle_close()挂钩方法被调用时,该类将自己删除。但是,必须保证MyEventHandler总是动态分配的,否则,全局内存堆可能会崩溃。确保类总是动态地创建的一种办法是将析构器移动到类的私有区域去。例如:

 

class MyEventHandler: public ACE_Event_Handler

{

public:

MyEventHandler(){//construct internal data members}

virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask mask)

{

dele te this; //commit suicide

}

 

private:

//Class must be allocated dynamically

~MyEventHandler(){//destroy internal data members}

};

 

6.2.2.2从反应堆内部分派表中显式拆除事件处理器

  另一种从反应堆的内部表中拆除事件处理器的方法是显式地调用反应堆的remove_handler()方法集。该方法也是重载方法,就像register_handler()一样。它采用需要拆除的处理器的句柄或信号号码作为参数,并将该处理器从反应堆的内部分派表中拆除。在remove_handler()被调用时,反应堆还自动调用事件处理器的handle_close()方法。可以这样来对其进行控制:将ACE_Event_Handler::DONT_CALL掩码传给remove_handler(),从而使得handle_close()方法不会被调用。更详尽的remove_handler()的使用例子将在下面的几个部分给出。

 

6.3 通过反应堆进行事件处理

  在下面的几个部分,我们将演示怎样将反应堆用于处理各种类型的事件。

 

6.3.1 I/O事件多路分离

  通过在具体的事件处理器类中重载handle_input()方法,反应堆可用于处理基于I/O设备的输入事件。这样的I/O可以发生在磁盘文件、管道、FIFO或网络socket上。为了进行基于I/O设备的事件处理,反应堆在内部使用从操作系统获取的设备句柄(在基于UNIX的系统中,该句柄是在文件或socket打开时,OS返回的文件描述符。在Windows中该局柄是由Windows返回的设备句柄)。网络应用显然是最适于这样的多路分离的应用之一。下面的例子演示反应堆是怎样与具体接受器一起使用来构造一个服务器的。

 

6-2

#include ”ace/Reactor.h”

#include ”ace/SOCK_Acceptor.h”

 

#define PORT_NO 19998

typedef ACE_SOCK_Acceptor Acceptor;

//forward declaration

class My_Accept_Handler;

 

class My_Input_Handler: public ACE_Event_Handler

{

public:

//Constructor

My_Input_Handler()

{

ACE_DEBUG((LM_DEBUG,”Constructor\n”);

}

 

//Called back to handle any input received

int handle_input(ACE_HANDLE)

{

//receive the data

peer().recv_n(data,12);

ACE_DEBUG((LM_DEBUG,”%s\n”,data));

 

// do something with the input received.

// ...

//keep yourself registered with the reactor

return 0;

}

 

//Used by the reactor to determine the underlying handle

ACE_HANDLE get_handle()const

{

return this->peer_i().get_handle();

}

 

//Returns a reference to the underlying stream.

ACE_SOCK_Stream &peer_i()

{

return this->peer_;

}

 

private:

ACE_SOCK_Stream peer_;

char data [12];

};

 

class My_Accept_Handler: public ACE_Event_Handler

{

public:

//Constructor

My_Accept_Handler(ACE_Addr &addr)

{

this->open(addr);

}

 

//Open the peer_acceptor so it starts to ”listen”

//for incoming clients.

int open(ACE_Addr &addr)

{

peer_acceptor.open(addr);

return 0;

}

 

//Overload the handle input method

int handle_input(ACE_HANDLE handle)

{

//Client has requested connection to server.

//Create a handler to handle the connection

My_Input_Handler *eh= new My_Input_Handler();

 

//Accept the connection ”into” the Event Handler

if (this->peer_acceptor.accept (eh->peer (), // stream

0, // remote address

0, // timeout

1) ==-1) //restart if interrupted

ACE_DEBUG((LM_ERROR,”Error in connection\n”));

 

ACE_DEBUG((LM_DEBUG,”Connection established\n”));

 

//Register the input event handler for reading

ACE_Reactor::instance()->

register_handler(eh,ACE_Event_Handler::READ_MASK);

 

//Unregister as the acceptor is not expecting new clients

return -1;

}

 

//Used by the reactor to determine the underlying handle

ACE_HANDLE get_handle(void) const

{

return this->peer_acceptor.get_handle();

}

 

private:

Acceptor peer_acceptor;

};

 

int main(int argc, char * argv[])

{

//Create an address on which to receive connections

ACE_INET_Addr addr(PORT_NO);

 

//Create the Accept Handler which automatically begins to “listen”

//for client requests for connections

My_Accept_Handler *eh=new My_Accept_Handler(addr);

 

//Register the reactor to call back when incoming client connects

ACE_Reactor::instance()->register_handler(eh,

ACE_Event_Handler::ACCEPT_MASK);

 

//Start the event loop

while(1)

ACE_Reactor::instance()->handle_events();

}

 

42/4<1234>
 

评分:0

我来说两句

seccode