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

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

ACE技术论文集-第8章 异步事件多路分离和分派处理器

发布: 2008-6-13 14:40 | 作者: Prashant Jain and D | 来源: 转载 | 查看: 430次

8.9 已知应用
 
下面是一些被广泛记载的前摄器的使用:
 
Windows NT中的I/O完成端口:Windows NT操作系统实现了前摄器模式。Windows NT支持多种Asynchronous Operation,比如接受新网络连接、读写文件和socket,以及通过网络连接传输文件。操作系统就是Asynchronous Operation Processor。操作结果在I/O完成端口(它扮演Completion Dispatcher的角色)上排队。
 
异步I/O操作的UNIX AIO族:在有些实时POSIX平台上,前摄器模式是由aio API族[9]来实现的。这些OS特性非常类似于上面描述的Windows NT的特性。一个区别是UNIX信号可用于实现真正异步的Completion Dispatcher(Windows NT API不是真正异步的)。
 
ACE ProactorACE自适配通信环境 [4]实现了前摄器组件,它封装Windows NT上的I/O完成端口,以及POSIX平台上的aio API。ACE前摄器抽象提供Windows NT所支持的标准C API的OO接口。这一实现的源码可从ACE网站http://www.cs.wustl.edu/~schmidt/ACE.html获取。
 
Windows NT中的异步过程调用(Asynchronous Procedure Call):有些系统(比如Windows NT)支持异步过程调用(APC)。APC是在特定线程的上下文中异步执行的函数。当APC被排队到线程时,系统发出软件中断。下一次线程被调度时,它将运行该APC。操作系统所发出的APC被称为内核模式APC。应用所发出的APC被称为用户模式APC。
 
8.10 相关模式
 
图8-9演示与前摄器相关的模式。
 
 
图8-9 前摄器模式的相关模式
 
异步完成令牌(ACT)模式[8]通常与前摄器模式结合使用。当Asynchronous Operation完成时,应用可能需要比简单的通知更多的信息来适当地处理事件。异步完成令牌模式允许应用将状态高效地与Asynchronous Operation的完成相关联。
前摄器模式还与观察者(Observer)模式[12](在其中,当单个主题变动时,相关对象也会自动更新)有关。在前摄器模式中,当来自多个来源的事件发生时,处理器被自动地通知。一般而言,前摄器模式被用于异步地将多个输入源多路分离给与它们相关联的事件处理器,而观察者通常仅与单个事件源相关联。
前摄器模式可被认为是同步反应堆模式[5]的一种异步的变体。反应堆模式负责多个事件处理器的多路分离和分派;它们在可以同步地发起操作而不会阻塞时被触发。相反,前摄器模式也支持多个事件处理器的多路分离和分派,但它们是被异步事件的完成触发的。
主动对象(Active Object)模式[13]使方法执行与方法调用去耦合。前摄器模式也是类似的,因为Asynchronous Operation Processor代表应用的Proactive Initiator来执行操作。就是说,两种模式都可用于实现Asynchronous Operation。前摄器模式常常用于替代主动对象模式,以使系统并发策略与线程模型去耦合。
前摄器可被实现为单体(Singleton)[12]。这对于在异步应用中,将事件多路分离和完成分派集中到单一的地方来说是有用的。
责任链(Chain of Responsibility,COR)模式[12]使事件处理器与事件源去耦合。在Proactive Initiator与Completion Handler的隔离上,前摄器模式也是类似的。但是,在COR中,事件源预先不知道哪一个处理器将被执行(如果有的话)。在前摄器中,Proactive Initiator完全知道目标处理器。但是,通过建立一个Completion Handler(它是由外部工厂动态配置的责任链的入口),这两种模式可被结合在一起:。
 
8.11 结束语
 
前摄器模式包含了一种强大的设计范式,支持高性能并发应用的高效而灵活的事件分派策略。前摄器模式提供并发执行操作的性能助益,而又不强迫开发者使用同步多线程或反应式编程。
 
参考文献
 
[1] J. Hu, I. Pyarali, and D. C. Schmidt, “Measuring the Impact of Event Dispatching and Concurrency Models on Web Server Performance Over High-speed Networks,” in Proceedings of the 2nd Global Internet Conference, IEEE, November 1997.
[2] J. Hu, I. Pyarali, and D. C. Schmidt, “Applying the Proactor Pattern to High-Performance Web Servers,” in Proceedings of the 10th International Conference on Parallel and Distributed Computing and Systems, IASTED, Oct. 1998.
[3] J. C. Mogul, “The Case for Persistent-connection HTTP,” in Proceedings of ACMSIGCOMM ’95 Conference in Computer Communication Review, (Boston, MA, USA), pp. 299–314, ACM Press, August 1995.
[4] D. C. Schmidt, “ACE: an Object-Oriented Framework for Developing Distributed Applications,” in Proceedings of the 6th USENIX C++ Technical Conference, (Cambridge, Massachusetts), USENIX Association, April 1994.
[5] D. C. Schmidt, “Reactor: An Object Behavioral Pattern for Concurrent Event Demultiplexing and Event Handler Dispatching,” in Pattern Languages of Program Design (J. O. Coplien and D. C. Schmidt, eds.), pp. 529–545, Reading, MA: Addison-Wesley, 1995.
[6] D. C. Schmidt, “Acceptor and Connector: Design Patterns for Initializing Communication Services,” in Pattern Languages of Program Design (R. Martin, F. Buschmann, and D. Riehle, eds.), Reading, MA: Addison-Wesley, 1997.
[7] M. K. McKusick, K. Bostic, M. J. Karels, and J. S. Quarterman, The Design and Implementation of the 4.4BSD Operating System. Addison Wesley, 1996.
[8] I. Pyarali, T. H. Harrison, and D. C. Schmidt, “Asynchronous Completion Token: an Object Behavioral Pattern for Efficient Asynchronous Event Handling,” in Pattern Languages of Program Design (R. Martin, F. Buschmann, and D. Riehle, eds.), Reading, MA: Addison-Wesley, 1997.
[9] “Information Technology – Portable Operating System Interface (POSIX) – Part 1: System Application: Program Interface (API) [C Language],” 1995.
[10] Microsoft Developers Studio, Version 4.2 - Software Development Kit, 1996.
[11] E. W. Dijkstra, “Hierarchical Ordering of Sequential Processes,” Acta Informatica, vol. 1, no. 2, pp. 115–138, 1971.
[12] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley, 1995.
[13] R. G. Lavender and D. C. Schmidt, “Active Object: an Object Behavioral Pattern for Concurrent Programming,” in Proceedings of the 2nd Annual Conference on the Pattern Languages of Programs, (Monticello, Illinois), pp. 1–7, September 1995.
 
附录A 可选实现
 
本附录概述用于开发前摄器模式的可选实现的代码。下面,我们检查使用多线程的同步I/O和使用单线程的反应式I/O。
 
A.1 多个同步线程
 
下面的代码显示怎样使用线程池同步I/O来开发Web服务器。当客户连接到服务器时,池中的一个线程接受连接,并调用HTTP_Handler中的open方法。随后服务器同步地从网络连接读取请求。当读操作完成时,客户请求随之被解析。在对GET请求的响应中,服务器对所请求文件进行内存映射,并将文件数据同步地写往客户。注意阻塞I/O是怎样使Web服务器能够遵循2.2.1中所概述的步骤的。
 
class HTTP_Handler
// = TITLE
// Implements the HTTP protocol
// (synchronous threaded version).
//
// = DESCRIPTION
// This class is called by a
// thread in the Thread Pool.
{
public:
void open (Socket_Stream *client)
{
HTTP_Request request;
 
// Store reference to client.
client_ = client;
 
// Synchronously read the HTTP request
// from the network connection and
// parse it.
client_->recv (request);
parse_request (request);
}
 
void parse_request (HTTP_Request &request)
{
// Switch on the HTTP command type.
switch (request.command ())
{
// Client is requesting a file.
case HTTP_Request::GET:
// Memory map the requested file.
Mem_Map input_file;
input_file.map (request.filename());
 
// Synchronously send the file
// to the client. Block until the
// file is transferred.
client_->send (input_file.data (),
input_file.size ());
break;
 
// Client is storing a file at
// the server.
case HTTP_Request::PUT:
// ...
}
}
 
private:
// Socket endpoint.
Socket_Stream *client_;
 
// ...
};
 
A.2 单线程反应式事件分派
 
下面的代码显示怎样将反应堆模式用于开发Web服务器。当客户连接到服务器时,HTTP_Handler::open方法被调用。服务器登记I/O句柄和在网络句柄“读就绪“时回调的对象(在此例中是this指针)。然后服务器返回事件循环。
当请求数据到达服务器时,reactor_回调HTTP_Handler::handle_input方法。客户数据以非阻塞方式被读取。如果有足够的数据,客户请求就被解析。如果整个客户请求还没有到达,应用就返回反应堆事件循环。
在对GET请求的响应中,服务器对所请求的文件进行内存映射;并在反应堆上登记,以在网络连接变为“写就绪”时被通知。当向连接写入数据不会阻塞调用线程时,reactor_就回调HTTP_Handler::handler_output方法。当所有数据都已发送给客户时,网络连接被关闭。
 
class HTTP_Handler :
public Reactor::Event_Handler
// = TITLE
// Implements the HTTP protocol
// (synchronous reactive version).
//
// = DESCRIPTION
// The Event_Handler base class
// defines the hooks for
// handle_input()/handle_output().
//
// = PATTERN PARTICIPANTS
// Reactor = Reactor
// Event Handler = HTTP_Handler
{
public:
void open (Socket_Stream *client)
{
// Initialize state for request
request_.state_ = INCOMPLETE;
 
// Store reference to client.
client_ = client;
 
// Register with the reactor for reading.
reactor_->register_handler
(client_->handle (),
this,
Reactor::READ_MASK);
}
 
// This is called by the Reactor when
// we can read from the client handle.
void handle_input (void)
{
int result = 0;
 
// Non-blocking read from the network
// connection.
do
result = request_.recv (client_->handle ());
while (result != SOCKET_ERROR && request_.state_ == INCOMPLETE);
 
// No more progress possible,
// blocking will occur
if (request_.state_ == INCOMPLETE && errno == EWOULDBLOCK)
reactor_->register_handler
(client_->handle (),
this,
Reactor::READ_MASK);
else
// We now have the entire request
parse_request ();
}
 
void parse_request (void)
{
// Switch on the HTTP command type.
switch (request_.command ())
{
// Client is requesting a file.
case HTTP_Request::GET:
 
// Memory map the requested file.
file_.map (request_.filename ());
 
// Transfer the file using Reactive I/O.
handle_output ();
break;
 
// Client is storing a file at
// the server.
case HTTP_Request::PUT:
// ...
}
}
 
void handle_output (void)
{
// Asynchronously send the file
// to the client.
if (client_->send (file_.data (),
file_.size ())
== SOCKET_ERROR
&& errno == EWOULDBLOCK)
// Register with reactor...
else
// Close down and release resources.
handle_close ();
}
 
private:
// Set at initialization.
Reactor *reactor_;
 
// Memory-mapped file_;
Mem_Map file_;
 
// Socket endpoint.
Socket_Stream *client_;
 
// HTTP Request holder.
HTTP_Request request_;
};
 
44/4<1234
 

评分:0

我来说两句

seccode

最新更新