??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久99精品一区二区,国内精品久久久久影院老司 ,狠狠色丁香婷婷久久综合http://www.shnenglu.com/walkspeed/category/3643.htmlzh-cnThu, 22 May 2008 21:01:48 GMTThu, 22 May 2008 21:01:48 GMT60接受器-q接器(Acceptor-ConnectorQ模?/title><link>http://www.shnenglu.com/walkspeed/archive/2007/02/27/19031.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Tue, 27 Feb 2007 13:47:00 GMT</pubDate><guid>http://www.shnenglu.com/walkspeed/archive/2007/02/27/19031.html</guid><wfw:comment>http://www.shnenglu.com/walkspeed/comments/19031.html</wfw:comment><comments>http://www.shnenglu.com/walkspeed/archive/2007/02/27/19031.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/walkspeed/comments/commentRss/19031.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/walkspeed/services/trackbacks/19031.html</trackback:ping><description><![CDATA[     摘要: 9.1 意图   接受器-q接器设计模式(Acceptor-ConnectorQ分布式系l中的连接徏立及服务初始化与一旦服务初始化后所执行的处理去耦合。这L去耦合通过三种lg来完成:acceptor、connector和service handlerQ服务处理器Q。连接器d地徏立到q地接受器组件的q接Qƈ初始化服务处理器来处理在q接上交...  <a href='http://www.shnenglu.com/walkspeed/archive/2007/02/27/19031.html'>阅读全文</a><img src ="http://www.shnenglu.com/walkspeed/aggbug/19031.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/walkspeed/" target="_blank">walkspeed</a> 2007-02-27 21:47 <a href="http://www.shnenglu.com/walkspeed/archive/2007/02/27/19031.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE的接受器QAcceptorQ和q接器(ConnectorQ:q接建立模式http://www.shnenglu.com/walkspeed/archive/2007/02/27/19030.htmlwalkspeedwalkspeedTue, 27 Feb 2007 13:40:00 GMThttp://www.shnenglu.com/walkspeed/archive/2007/02/27/19030.htmlhttp://www.shnenglu.com/walkspeed/comments/19030.htmlhttp://www.shnenglu.com/walkspeed/archive/2007/02/27/19030.html#Feedback1http://www.shnenglu.com/walkspeed/comments/commentRss/19030.htmlhttp://www.shnenglu.com/walkspeed/services/trackbacks/19030.html阅读全文

walkspeed 2007-02-27 21:40 发表评论
]]>
转蝲一片关于前摄器QProactorQ的文章http://www.shnenglu.com/walkspeed/archive/2007/02/27/19029.htmlwalkspeedwalkspeedTue, 27 Feb 2007 13:17:00 GMThttp://www.shnenglu.com/walkspeed/archive/2007/02/27/19029.htmlhttp://www.shnenglu.com/walkspeed/comments/19029.htmlhttp://www.shnenglu.com/walkspeed/archive/2007/02/27/19029.html#Feedback0http://www.shnenglu.com/walkspeed/comments/commentRss/19029.htmlhttp://www.shnenglu.com/walkspeed/services/trackbacks/19029.html W?/b> 8 ?/b> 前摄器( Proactor Q:用于为异步事件多路分d分派处理器的对象行ؓ模式
 
Irfan Pyarali   Tim Harrison   Douglas C. Schmidt   Thomas D. Jordan
 
?/b> ?/b>
 
C操作pȝ为开发ƈ发应用提供了多种机制。同步多U程是一U流行的机制Q用于开发同时执行多个操作的应用。但是,U程常常有很高的性能开销Qƈ且需要对同步模式和原理有深入的了解。因此,有越来越多的操作pȝ支持异步机制Q在减少多线E的大量开销和复杂性的同时Q提供了q发的好处?/i>
本论文中介绍的前摄器QProactor Q模式描q怎样构造应用和pȝQ以有效地利用操作系l支持的异步机制。当应用调用异步操作ӞOS 代表应用执行此操作。这使得应用可以让多个操作同时运行,而又不需要应用拥有相应数目的U程。因此,通过使用更少的线E和有效利用OS 对异步操作的支持Q前摄器模式化了q发~程Qƈ改善了性能?/i>
 
8.1 意图
 
前摄器模式支持多个事件处理器的多路分d分派Q这些处理器由异步事件的完成来触发。通过集成完成事gQcompletion eventQ的多\分离和相应的事g处理器的分派Q该模式化了异步应用的开发?/div>
 
8.2 动机
 
q一部分提供使用前摄器模式的上下文和动机?/div>
 
8.2.1 上下文和压力
 
前摄器模式应该被用于应用需要ƈ发执行操作的性能好处、又不想受到同步多线E或反应式编E的U束时。ؓ说明q些好处Q设想一个需要ƈ发执行多个操作的|络应用。例如,一个高性能Web服务器必dƈ发处理发送自多个客户的HTTPh[1, 2]。图8-1 昄了Web览器和Web服务器之间的典型交互。当用户指示览器打开一个URLӞ览器发送一个HTTP GEThlWeb服务器。收到请求,服务器就解析q校验请求,q将指定的文件发回给览器?/div>
 
 
?-1 典型的Web服务器通信软g体系l构
 
开发高性能Web服务器要求消除以下压力:
 
  • q发?/i>Q服务器必须同时执行多个客户hQ?
  • 效率Q服务器必须最化响应延迟、最大化吞吐量,q免不必要C用CPUQ?
  • ~程单?/i>Q服务器的设计应该简化高效的q发{略的用;
  • 可适配?/i>Q应该ɾl承新的或改q的传输协议Q比如HTTP 1.1[3]Q所带来的维护代h化?
 
Web服务器可以用若qƈ发策略来实现Q包括多个同步线E、反应式同步事g分派和前摄式异步事g分派。下面,我们查传l方法的~点Qƈ解释前摄器模式是怎样提供一U强大的技术,为高性能q发应用而支持高效、灵zȝ异步事g分派{略的?/div>
 
8.2.2 传统q发模型的常见陷阱和~陷
 
同步的多U程和反应式~程是实现ƈ发的常用Ҏ(gu)。这一部分描述q些~程模型的缺炏V?/div>
 
8.2.2.1 通过多个同步U程实现的ƈ?/b>
 
或许最为直观的实现q发Web服务器的途径是?i>同步的多U程。在此模型中Q多个服务器U程同时处理来自多个客户的HTTP GETh。每个线E同步地执行q接建立、HTTPhd、请求解析和文g传输操作。作为结果,每个操作都阻塞直到完成?/div>
同步U程的主要优Ҏ(gu)应用代码的简化。特别是QWeb服务器ؓ服务客户A的请求所执行的操作在很大E度上独立于为服务客户B的请求所需的操作。因而,很容易在分离的线E中对不同的hq行服务Q因为在U程之间׃n的状态数量很;q也最化了对同步的需要。而且Q在分离的线E中执行应用逻辑也得开发者可以用直观的序命o和阻塞操作?/div>
 
 
?-2 多线EWeb服务器体pȝ?/div>
 
?-2昄使用同步U程来设计的Web服务器怎样q发地处理多个客戯求。该图显C的Sync Acceptor对象装服务器端用于同步接受|络q接的机制。用“Thread Per Connection”ƈ发模型,各个U程为服务HTTP GETh所执行的一pd步骤可被ȝ如下Q?/div>
 
  1. 每个U程同步地阻塞在accept socket调用中,{待客户q接hQ?
  2. 客户q接到服务器Q连接被接受Q?
  3. 新客LHTTPh被同步地从网l连接中dQ?
  4. h被解析;
  5. 所h的文件被同步地读取;
  6. 文g被同步地发送给客户?
 
附录A.1中有一个将同步U程模型应用于Web服务器的C++代码例子?/div>
如上所qͼ每个q发地连接的客户׃个专用的服务器线E服务。在l箋为其他HTTPh服务之前Q该U程同步地完成一个被h的操作。因此,要在服务多个客户时执行同步I/OQWeb服务器必L生多个线E。尽这U同步线E模式是直观的,且能够相寚w效地映射到多CPUq_上,它还是有以下~点Q?/div>
 
U程{略与ƈ发策略被紧耦合Q?/b>q种体系l构要求每个相连客户都有一个专用的U程。通过针对可用资源Q比如用线E池来对应CPU的数目)、而不是正被ƈ发服务的客户的数目来调整其线E策略,可能会更好地优化一个ƈ发应用;
 
更大的同步复杂性:U程可能会增加序列化Ҏ(gu)务器的共享资源(比如~存文g和Web面点击日志Q的讉K所必需的同步机制的复杂性;
 
更多的性能开销Q?/b>׃上下文切换、同步和CPU间的数据Ud[4]Q线E的执行可能很低效;
 
不可UL性:U程有可能在有些q_上不可用。而且Q根据对占先式和非占先式U程的支持,OSq_之间的差异非常大。因而,很难构徏能够跨^台统一q作的多U程服务器?/div>
 
作ؓq些~点的结果,多线E常怸是开发ƈ发Web服务器的最为高效的、也不是最不复杂的解决Ҏ(gu)?/div>
 
8.2.2.2 通过反应式同步事件分z֮现的q发
 
另一U实现同步Web服务器的常用Ҏ(gu)是?i>反应式事件分z?/i>模型。反应堆QReactorQ模式描q应用怎样Event Handler登记到Initiation Dispatcher。Initiation Dispatcher通知Event Handler何时能发起一Ҏ(gu)作而不d?/div>
单线Eƈ发Web服务器可以用反应式事g分派模型Q它在一个事件@环中{待Reactor通知它发起适当的操作。Web服务器中反应式操作的一个例子是AcceptorQ接受器Q[6]到Initiation Dispatcher的登记。当数据在网l连接上到达Ӟ分派器回调AcceptorQ后者接受网l连接,q创建HTTP Handler。于是这个HTTP Handlerq记到ReactorQ以在Web服务器的单线E控制中处理在那个连接上到来的URLh?/div>
?-3和图8-4昄使用反应式事件分z设计的Web服务器怎样处理多个客户。图8-3昄当客戯接到Web服务器时所采取的步骤。图8-4昄Web服务器怎样处理客户h。图8-3的一pd步骤可被ȝ如下Q?/div>
 
 
?-3 客户q接到反应式Web服务?/div>
 
 
?-4 客户发送HTTPh到反应式Web服务?/div>
 
  1. Web服务器将Acceptor登记到Initiation DispatcherQ以接受新连接;
  2. Web服务器调用Initiation Dispatcher的事件@环;
  3. 客户q接到Web服务器;
  4. Initiation Dispatcher新q接h通知AcceptorQ后者接受新q接Q?
  5. Acceptor创徏HTTP HandlerQ以服务新客P
  6. HTTP Handler连接登记到Initiation DispatcherQ以d客户h数据Q就是说Q在q接变得“读qA”时Q;
  7. HTTP Handler服务来自新客Lh?
 
?-4昄反应式Web服务器ؓ服务HTTP GETh所采取的一pd步骤。该q程描述如下Q?/div>
 
  1. 客户发送HTTP GEThQ?
  2. 当客戯求数据到达服务器ӞInitiation Dispatcher通知HTTP HandlerQ?
  3. h以非d方式被读取,于是如果操作会导致调用线E阻塞,L作就q回EWOULDBLOCKQ步??重复直到请求被完全dQ;
  4. HTTP Handler解析HTTPhQ?
  5. 所h的文件从文gpȝ中被同步dQ?
  6. 为发送文件数据(是_当连接变得“写qA”时Q,HTTP Handler连接登记到Initiation DispatcherQ?
  7. 当TCPq接变得写就l时QInitiation Dispatcher通知HTTP HandlerQ?
  8. HTTP Handler以非d方式所h文g发送给客户Q于是如果操作会D调用U程dQ写操作p回EWOULDBLOCKQ步??重复直到数据被完全递送)?
 
附录A.2中有一个将反应式事件分z模型应用于Web服务器的C++代码例子?/div>
因ؓInitiation Dispatcherq行在单U程中,|络I/O操作以非d方式q行在Reactor的控制之下。如果当前操作的q度停止了,操作p转手lInitiation DispatcherQ由它监控系l操作的状态。当操作可以再度前进Ӟ适当的Event Handler会被通知?/div>
反应式模式的主要优点是可UL性,_粒度ƈ发控制带来的低开销Q就是说Q单U程不需要同步或上下文切换)Q以及通过使应用逻辑与分z机制去耦合所获得的模块性。但是,该方法有以下~点Q?/div>
 
复杂的编E:如从前面的列表所看到的,E序员必ȝ写复杂的逻辑Q以保证服务器不会在服务一个特定客hd?/div>
 
~Z多线E的OS 支持Q?/b>大多数操作系l通过selectpȝ调用[7]来实现反应式分派模型。但是,select不允许多于一个的U程在同一个描q符集上{待。这使得反应式模型不适用于高性能应用Q因为它没有有效地利用硬件的q行性?/div>
 
可运行Q务的调度Q?/b>在支持占先式U程的同步多U程体系l构中,可q行U程调度q时分(time-sliceQ到可用CPU上是操作pȝ的责仅R这L调度支持在反应式体系l构中不可用Q因为在应用中只有一个线E。因此,pȝ的开发者必d心地在所有连接到Web服务器的客户之间线E分时。这只能通过执行短持l时间、非d的操作来完成?/div>
 
作ؓq些~点的结果,当硬件ƈ行可用时Q反应式事g分派不是最为高效的模型。由于需要避免用阻塞I/OQ该模式q有着相对较高的编E复杂度?/div>
 
8.2.3 解决Ҏ(gu)Q通过前摄式操作实现的q发
 
当OSq_支持异步操作Ӟ一U高效而方便的实现高性能Web服务器的Ҏ(gu)是?i>前摄式事件分z?/i>。用前摄式事g分派模型设计的Web服务器通过一或多个线E控制来处理异步操作的完成。这P通过集成完成事g多\分离Q?/i>completion event demultiplexingQ和事g处理器分z,前摄器模式简化了异步的Web服务?/i>?/div>
异步的Web服务器将q样来利用前摄器模式Q首先让Web服务器向OS发出异步操作Qƈ回调方法登记到Completion DispatcherQ完成分z֙Q,后者将在操作完成时通知Web服务器。于是OS代表Web服务器执行操作,q卛_一个周知的地方结果排队。Completion Dispatcher负责使完成通知出队Qƈ执行适当的、含有应用特有的Web服务器代码的回调?/div>
 
 
?-5 客户q接到基于前摄器的Web服务?/div>
 
 
?-6 客户发送请求给Z前摄器的Web服务?/div>
 
?-5和图8-6昄使用前摄式事件分z设计的Web服务器怎样在一或多个线E中q发地处理多个客戗图8-5昄当客戯接到Web服务器时所采取的一pd步骤?/div>
 
  1. Web服务器指CAcceptor发v异步接受Q?
  2. 接受器通过OS发v异步接受Q将其自w作为Completion Handler和Completion Dispatcher的引用传递;q将用于在异步接受完成时通知AcceptorQ?
  3. Web服务器调用Completion Dispatcher的事件@环;
  4. 客户q接到Web服务器;
  5. 当异步接受操作完成时Q操作系l通知Completion DispatcherQ?
  6. Completion Dispatcher通知接受器;
  7. Acceptor创徏HTTP HandlerQ?
  8. HTTP Handler发v异步操作Q以d来自客户的请求数据,q将其自w作为Completion Handler和Completion Dispatcher的引用传递;q将用于在异步读取完成时通知HTTP Handler?
 
?-6 昄前摄式Web服务器ؓ服务HTTP GETh所采取的步骤。这些步骤解释如下:
 
  1. 客户发送HTTP GEThQ?
  2. d操作完成Q操作系l通知Completion DispatcherQ?
  3. Completion Dispatcher通知HTTP HandlerQ步??重复直到整个请求被接收Q;
  4. HTTP Handler解析hQ?
  5. HTTP Handler同步地读取所h的文Ӟ
  6. HTTP Handler发v异步操作Q以把文件数据写到客戯接,q将其自w作为Completion Handler和Completion Dispatcher的引用传递;q将用于在异步写入完成时通知HTTP Handler?
  7. 当写操作完成Ӟ操作pȝ通知Completion DispatcherQ?
  8. 随后Completion Dispatcher通知Completion HandlerQ步?-8重复直到文件被完全递送)?
 
8.8中有一个将前摄式事件分z模型应用于Web服务器的C++代码例子?/div>
使用前摄器模式的主要优点是可以启动多个ƈ发操作,q可q行q行Q而不要求应用必须拥有多个U程。操作被应用异步地启动,它们在OS的I/O子系l中q行直到完成。发h作的U程现在可以服务另外的请求了?/div>
例如Q在上面的例子中QCompletion Dispatcher可以是单U程的。当HTTPh到达Ӟ单个Completion DispatcherU程解析hQ读取文Ӟq发送响应给客户。因为响应是被异步发送的Q多个响应就有可能同时被发送。而且Q同步的文gd可以被异步的文gd取代Q以q一步增加ƈ发的潜力。如果文件读取是被异步完成的QHTTP Handler所执行的唯一的同步操作就只剩下了HTTP协议h解析?/div>
前摄式模型的主要~点是编E逻辑臛_和反应式模型一样复杂。而且Q前摄器模式可能会难以调试,因ؓ异步操作常常有着不可预测和不可重复的执行序列Q这׃分析和调试复杂化了?.7描述怎样应用其他模式Q比如异步完成o牌[8]Q来化异步应用编E模型?/div>
 
8.3 适用?/b>
 
当具有以下一Ҏ(gu)多项条g时用前摄器模式Q?/div>
 
  • 应用需要执行一个或多个不阻塞调用线E的异步操作Q?
  • 当异步操作完成时应用必须被通知Q?
  • 应用需要独立于它的I/O模型改变它的q发{略Q?
  • 通过使依赖于应用的逻辑与应用无关的底层构造去耦合Q应用将从中LQ?
  • 当用多U程Ҏ(gu)或反应式分派Ҏ(gu)Ӟ应用的执行将很低效,或是不能满性能需求?
 
8.4 l构和参与?/b>
 
在图8-7中用OMT表示法演CZ前摄器模式的l构?/div>
前摄器模式中的关键参与者包括:
 
前摄发v?/b>QProactive Initiator。Web服务器应用的ȝE)Q?/div>
 
  • Proactive Initiator是应用中M发vAsynchronous OperationQ异步操作)的实体。它?yu)Completion Handler和Completion Dispatcher登记到Asynchronous Operation ProcessorQ异步操作处理器Q,此处理器在操作完成时通知前摄发v器?
 
完成处理?/b>QCompletion Handler。Acceptor和HTTP HandlerQ:
 
  • 前摄器模式将应用所实现的Completion Handler接口用于Asynchronous Operation完成通知?
 
异步操作QAsynchronous Operation。Async_Read、Async_Write和Async_AcceptҎ(gu)Q:
 
  • Asynchronous Operation被用于代表应用执行请求(比如I/O和定时器操作Q。当应用调用Asynchronous OperationӞ操作的执?i>没有借用应用的线E控制。因此,从应用的角度来看Q操作是?i>异步?/i>执行的。当Asynchronous Operation完成ӞAsynchronous Operation Processor应用通知委托lCompletion Dispatcher?
 
异步操作处理?/b>QAsynchronous Operation Processor。操作系l)Q?/div>
 
  • Asynchronous Operation是由Asynchronous Operation Processor来运行直臛_成的。该lg通常由O(jin)S实现?
 
完成分派?/b>QCompletion Dispatcher。Notification QueueQ:
 
  • Completion Dispatcher负责在Asynchronous Operation完成时回调应用的Completion Handler。当Asynchronous Operation Processor完成异步发v的操作时QCompletion Dispatcher代表应用执行应用回调?
 
 
?-7 前摄器模式中的参与?/div>
 
8.5 协作
 
有若q良好定义的步骤被用于所有Asynchronous Operation。在高水q的抽象上,应用异步地发h作,q在操作完成时被通知。图8-8昄在模式参与者之间必定发生的下列交互Q?/div>
 
  1. 前摄发v器发h作:为执行异步操作,应用在Asynchronous Operation Processor上发h作。例如,Web服务器可能要求OS在网l上使用特定的socketq接传输文g。要hq样的操作,Web服务器必L定要使用哪一个文件和|络q接。而且QWeb服务器必L定(1Q当操作完成旉知哪一个Completion HandlerQ以及(2Q一旦文件被传输Q哪一个Completion Dispatcher应该执行回调?
  2. 异步操作处理器执行操作:当应用在Asynchronous Operation Processor上调用操作时Q它相对于其他应用操作异步地q行q些操作。现代操作系l(比如Solaris和Windows NTQ在内核中提供异步的I/O子系l?
  3. 异步操作处理器通知完成分派器:当操作完成时QAsynchronous Operation Processor取得在操作被发v时指定的Completion Handler和Completion Dispatcher。随后Asynchronous Operation ProcessorAsynchronous Operation的结果和Completion Handler传递给Completion DispatcherQ以用于回调。例如,如果文g已被异步传输QAsynchronous Operation Processor可以报告完成状态(比如成功或失败)Q以及写入网l连接的字节数?
  4. 完成分派器通知应用Q?/b>Completion Dispatcher在Completion Handler上调用完成挂钩,由应用指定的Q何完成数据传递给它。例如,如果异步d完成Q通常一个指向新到达数据的指针将会被传递给Completion Handler?
 
 
?-8 前摄器模式的交互?/div>
 
8.6 效果
 
q一部分详述使用前摄器模式的效果?/div>
 
8.6.1 好处
 
前摄器模式提供以下好处:
 
增强事务分离Q?/b>前摄器模式应用无关的异步机制与应用Ҏ(gu)的功能去耦合。应用无关的机制成ؓ可复用组Ӟ知道怎样多\分离与Asynchronous Operation相关联的完成事gQƈ分派适当的由Completion Handler定义的回调方法。同样地Q应用特有的功能知道怎样执行特定cd的服务(比如HTTP处理Q?/div>
 
改善应用逻辑可移植性:通过允许接口独立于执行事件多路分ȝ底层OS调用而复用,它改善了应用的可UL性。这些系l调用检ƈ报告可能同时发生在多个事件源之上的事件。事件源可以是I/O端口、定时器、同步对象、信P{等。在实时POSIXq_上,异步I/O函数由aio API族[9]提供。在Windows NT中,I/O完成端口和重叠式QoverlappedQI/O被用于实现异步I/O[10]?/div>
 
完成分派器封装了q发机制Q?/b>使Completion Dispatcher与Asynchronous Operation Processor去耦合的一个好处是应用可以通过多种q发{略来配|Completion DispatcherQ而不会媄响其他参与者。如8.7所讨论的,Completion Dispatcher可被配置使用包括单线E和U程池方案在内的若干q发{略?/div>
 
U程{略被与q发{略去耦合Q?/b>因ؓAsynchronous Operation Processor代表Proactive Initiator完成可能长时间运行的操作Q应用不会被q派生线E来增加q发。这使得应用可以独立于它的线E策略改变它的ƈ发策略。例如,Web服务器可能只x个CPU有一个线E,但又惛_时服务更多数目的客户?/div>
 
提高性能Q?/b>多线E操作系l执行上下文切换Q以在多个线E控制中轮换。虽然执行一ơ上下文切换的时间保持相当的恒定Q如果OS上下文要切换到空闲线E的话,在大量线E间轮换的L间可以显著地降低应用性能。例如,U程可以轮询OS以查看完成状态,而这是低效率的。通过只激z那些有事g要处理的合理的线E控Ӟ前摄器模式能够避免上下文切换的代仗例如,如果没有待处理的GEThQWeb服务器不需要启用HTTP Handler?/div>
 
应用同步的简化:只要Completion Handler不派生另外的U程控制Q可以不考虑、或只考虑许同步问题而编写应用逻辑。Completion Handler可被~写为就好像它们存在于一个传l的单线E环境中一栗例如,Web服务器的HTTP GET处理器可以通过Async Read操作Q比如Windows NT TransmitFile函数[1]Q来讉K盘?/div>
 
8.6.2 ~点
 
前摄器模式有以下~点Q?/div>
 
难以调试Q?/b>以前摄器模式~写的应用可能难以调试,因ؓ反向的控制流在构架基l构和应用特有的处理器上的回调方法之间来回振荡。这增加了在调试器中Ҏ(gu)架的q行时行为的“单步跟t”的困难度,因ؓ应用开发者可能不了解或不能获得构架的代码。这与试图调试用LEX和YACC~写的编译器的词法分析器和解析器时所遇到的问题是cM的。在q些应用中,当线E控制是在用户定义的动作例程中时Q调试是相当直接的。但是一旦线E控制返回到所生成的有限确定自动机QDeterministic Finite AutomateQDFAQ骨架时Q就很难跟住E序逻辑了?/div>
 
调度和控制未完成操作Q?/b>Proactive Initiator可能没有对Asynchronous Operation的执行顺序的控制。因此,Asynchronous Operation Processor必须被小心设计,以支持Asynchronous Operation的优先和取消处理?/div>
 
8.7 实现
 
前摄器模式可以通过许多方式实现。这一部分讨论实现前摄器模式所涉及的步骤?/div>
 
8.7.1 实现异步操作处理?/b>
 
实现前摄器模式的W一步是构徏Asynchronous Operation Processor。该lg负责代表应用异步地执行操作。因此,它的两项主要责Q是输出Asynchronous Operation API和实现Asynchronous Operation Engine以完成工作?/div>
 
8.7.1.1 定义异步操作 API
 
Asynchronous Operation Processor必须提供API、允许应用请求Asynchronous Operation。在设计q些API时有若干压力需要考虑Q?/div>
 
可移植性:此API不应U束应用或它的Proactive Initiator使用特定的^台?/div>
 
灉|性:常常Q异步API可以多类型的操作׃n。例如,异步I/O操作常常被用于在多种介质Q比如网l和文gQ上执行I/O。设计支持这L复用的API可能是有益的?/div>
 
回调Q?/b>当操作被调用ӞProactive Initiator必须登记回调。实现回调的一U常用方法是让调用对象(客户Q输出接口、让调用者知道(服务器)。因此,Proactive Initiator必须通知Asynchronous Operation ProcessorQ当操作完成Ӟ哪一个Completion Handler应被回调?/div>
 
完成分派器:因ؓ应用可以使用多个Completion DispatcherQProactive Initiatorq必LC由哪一个Completion Dispatcher来执行回调?/div>
 
l定所有这些问题,考虑下面的用于异步读写的API。Asynch_StreamcL用于发v异步d的工厂。一旦构造,可以使用此类来启动多个异步读写。当异步d完成ӞAsynch_Stream::Read_Result通过Completion_Handler上的handler_read回调Ҏ(gu)被回传给handler。类似地Q当异步写入完成ӞAsynch_Stream::Write_Result通过Completion_Handler上的handler_write回调Ҏ(gu)被回传给handler?/div>
 
class Asynch_Stream
// = TITLE
// A Factory for initiating reads
// and writes asynchronously.
{
// Initializes the factory with information
// which will be used with each asynchronous
// call. <handler> is notified when the
// operation completes. The asynchronous
// operations are performed on the <handle>
// and the results of the operations are
// sent to the <Completion_Dispatcher>.
Asynch_Stream (Completion_Handler &handler,
HANDLE handle,
Completion_Dispatcher *);
 
// This starts off an asynchronous read.
// Upto <bytes_to_read> will be read and
// stored in the <message_block>.
int read (Message_Block &message_block,
u_long bytes_to_read,
const void *act = 0);
 
// This starts off an asynchronous write.
// Upto <bytes_to_write> will be written
// from the <message_block>.
int write (Message_Block &message_block,
u_long bytes_to_write,
const void *act = 0);
 
...
};
 
8.7.1.2 实现异步操作引擎
 
Asynchronous Operation Processor必须含有异步执行操作的机制。换句话_当应用线E调用Asynchronous OperationӞ必须不借用应用的线E控制而执行此操作。幸好,C操作pȝ提供了用于Asynchronous Operation的机Ӟ例如QPOSIX 异步I/O和WinNT重叠式I/OQ。在q样的情况下Q实现模式的q一部分只需要简单地^台API映射C面描q的Asynchronous Operation API?/div>
如果OSq_不提供对Asynchronous Operation的支持,有若q实现技术可用于构徏Asynchronous Operation Engine。或许最为直观的解决Ҏ(gu)是用专用线E来为应用执行Asynchronous Operation。要实现U程化的Asynchronous Operation EngineQ有三个主要步骤Q?/div>
 
  1. 操作调用Q?/b>因ؓ操作在与进行调用的应用U程不同的线E控制中执行Q必定会发生某种cd的线E同步。一U方法是为每个操作派生一个线E。更为常用的Ҏ(gu)是ؓAsynchronous Operation Processor而管理一个专用线E池。该Ҏ(gu)可能需要应用线E在l箋q行其他应用计算之前操作请求排队?
  2. 操作执行Q?/b>既然操作在专用U程中执行,所以它可以执行“阻塞”操作,而不会直接阻应用的q展。例如,在提供异步I/Od机制Ӟ专用U程可以在从socket或文件句柄中Ld?
  3. 操作完成Q?/b>当操作完成时Q应用必被通知到。特别是Q专用线E必d应用Ҏ(gu)的通知委托lCompletion Dispatcher。这要求在线E间q行另外的同步?
 
8.7.2 实现完成分派?/b>
 
当Completion Dispatcher从Asynchronous Operation Processor接收到操作完成通知Ӟ它会回调与应用对象相兌的Completion Handler。实现Completion Dispatcher涉及两个问题Q(1Q实现回调以及(2Q定义用于执行回调的q发{略?/div>
 
8.7.2.1 实现回调
 
Completion Dispatcher必须实现一U机ӞCompletion Handler通过它被调用。这要求Proactive Initiator在发h作时指定一个回调。下面是常用的回调可选方案:
 
回调c:Completion Handler输出接口、让Completion Dispatcher知道。当操作完成ӞCompletion Dispatcher回调此接口中的方法,q将已完成操作的有关信息传递给它(比如从网l连接中d的字节数Q?/div>
 
函数指针Q?/b>Completion Dispatcher通过回调函数指针来调用Completion Handler。该Ҏ(gu)有效地打破了Completion Dispatcher和Completion Handler之间的知识依赖。这有两个好处:
 
  1. Completion Handler不会被迫输出特定的接口;以及
  2. 在Completion Dispatcher和Completion Handler之间不需要有~译时依赖?
 
会合点:Proactive Initiator可以讄事g对象或条件变量,用作Completion Dispatcher和Completion Handler之间的会合点。这在Completion Handler是Proactive Initiator时最为常见。在Asynchronous Operationq行臛_成的同时QCompletion Handler处理其他的活动。Completion Handler在会合点周期性地查完成状态?/div>
 
8.7.2.2 定义完成分派器ƈ发策?/b>
 
当操作完成时QAsynchronous Operation Processor会通知Completion Dispatcher。在q时QCompletion Dispatcher可以利用下面的ƈ发策略中的一U来执行应用回调Q?/div>
 
动态线E分z:Completion Dispatcher可ؓ每个Completion Handler动态分配一个线E。动态线E分z֏通过大多数多U程操作pȝ来实现。在有些q_上,׃创徏和销毁线E资源的开销Q这可能是所列出的Completion Dispatcher实现技术中最Z效的一U,
 
后反应式分派QPost-reactive dispatching Q:Completion Dispatcher可以发信LProactive Initiation所讄的事件对象或条g变量。尽轮询和zd在事件对象上的子U程都是可选的Ҏ(gu)Q最为高效的后反应式分派Ҏ(gu)是将事g登记到Reactor。后反应式分z֏以通过POSIX实时环境中的aio_suspend和Win32环境中的WaitForMultipleObjects来实现?/div>
 
Call-through 分派Q?/b>来自Asynchronous Operation Processor的线E控制可被Completion Dispatcher借用Q以执行Completion Handler。这U“周期偷取”策略可以通过减少I闲U程的媄响范围来提高性能。在一些老操作系l会上下文切换到空闲线E、又只是从它们切换出ȝ情况下,q种Ҏ(gu)有着收回“失ȝ”时间的巨大潜力?/div>
Call-through分派在Windows NT中可以用ReadFileEx和WriteFileEx Win32函数来实现。例如,U程控制可以使用q些调用来等待信号量被置位。当它等待时Q线E通知OS它进入了一U称为“可报警{待状态”(alterable wait stateQ的Ҏ(gu)状态。在q时QOS可以占有对等待中的线E控制的栈和相关资源的控Ӟ以执行Completion Handler?/div>
 
U程池分z:由Completion Dispatcher拥有的线E池可被用于Completion Handler的执行。在池中的每个线E控制已被动态地分配到可用的CPU。线E池分派可通过Windows NT的I/O完成端口来实现?/div>
 
在考虑上面描述的Completion Dispatcher技术的适用性时Q考虑?-1中所C的OS环境和物理硬件的可能l合  Q?br />

U程模型
pȝcd
单处理器
多处理器
单线E?/div>
A
B
多线E?/div>
C
D
?-1 Completion Dispatcherq发{略
 
如果你的OS只支持同步I/OQ那参见反应堆模式[5]。但是,大多数现代操作系l都支持某种cd的异步I/O?/div>
在表8-1的A和Bl合中,假定你不{待M信号量或互斥体,后反应方式的异步I/O很可能是最好的。否则,Call-through实现或许更能回应你的问题。在Cl合中,使用Call-throughҎ(gu)。在Dl合中,使用U程池方法。在实践中,pȝ化的l验量对于选择最为合适的可选方案来说是必需的?/div>
 
8.7.3 实现完成处理?/b>
 
Completion Handler的实现带来以下考虑?/div>
 
8.7.3.1 状态完整?/b>
 
Completion Handler可能需要维护关于特定请求的状态信息。例如,OS可以通知Web服务器,只有一部分文g已被写到|络通信端口。作为结果,Completion Handler可能需要重新发求,直到文g被完全写出,或连接变得无效。因此,它必ȝ道原先指定的文gQ还剩多字节要写,以及在前一个请求开始时文g指针的位|?/div>
没有隐含的限制来LProactive Initiator多个Asynchronous Operationh分配l单个Completion Handler。因此,Completion Handler必须在完成通知链中一一“系上”请求特有的状态信息。ؓ完成此工作,Completion Handler可以利用异步完成令牌QAsynchronous Completion TokenQ模式[8]?/div>
 
8.7.3.2 资源理
 
与在M多线E环境中一P使用前摄器模式的Completion Handlerq是要由它自己来保对共享资源的讉K是线E安全的。但是,Completion Handler不能跨越多个完成通知持有׃n资源。否则,有发生“用哲学家问题”的危险[11]?/div>
该问题在于一个合理的U程控制怹{待一个信号量被置位时所产生的死锁。通过设想一个由一哲学家出席的宴会可以演C一问题。用者围l一个圆桌就座,在每个哲学家之间只有一支筷子。当哲学家觉得饥饿时Q他必须获取在他左边和在他右边的{子才能用餐。一旦哲学家获得一支筷子,不到吃饱他们׃会放下它。如果所有哲学家都拿起在他们双的筷子,׃发生死锁Q因Z们将永远也不可能拿到左边的筷子?/div>
 
8.7.3.3 占先式策略(Preemptive PolicyQ?/b>
 
Completion Dispatchercd军_在执行时一个Completion Handler是否可占先。当与动态线E和U程池分z֙相连ӞCompletion Handler自然可占先。但是,当与后反应式Completion Dispatcher相连ӞCompletion Handlerq没有对其他Completion Handler的占先权。当由Call-through分派器驱动时QCompletion Handler相对于在可报警等待状态的U程控制也没有占先权?/div>
一般而言Q处理器不应该执行持l时间长的同步操作,除非使用了多个完成线E,因ؓ应用的M响应性将会被显著地降低。这L危险可以通过增强的编E训l来降低。例如,所有Completion Handler被要求用作Proactive InitiatorQ而不是去执行同步操作?/div>
 
8.8 CZ代码
 
q一部分昄怎样使用前摄器模式来开发Web服务器。该例子ZACE构架[4]中的前摄器实现?/div>
当客戯接到Web服务器时QHTTP_Handler的openҎ(gu)被调用。于是服务器通过在Asynchronous Operation完成时回调的对象Q在此例中是this指针Q、用于传输数据的|络q接Q以及一旦操作完成时使用的Completion DispatcherQproactor_Q来初始化异步I/O对象。随后读操作异步地启动,而服务器q回事g循环?/div>
当Async read操作完成Ӟ分派器回调HTTP_Handler::handle_read_stream。如果有_的数据,客户hp解析。如果整个客戯求还未完全到达,另一个读操作׃被异步地发v?/div>
在对GETh的响应中Q服务器Ҏ(gu)h文gq行内存映射Qƈ文件数据异步地写往客户。当写操作完成时Q分z֙回调HTTP_Handler::handle_write_streamQ从而释攑֊态分配的资源?/div>
附录中含有两个其他的代码实例Q用同步的U程模型和同步的Q非dQ反应式模型实现Web服务器?/div>
 
class HTTP_Handler
: public Proactor::Event_Handler
// = TITLE
// Implements the HTTP protocol
// (asynchronous version).
//
// = PATTERN PARTICIPANTS
// Proactive Initiator = HTTP_Handler
// Asynch Op = Network I/O
// Asynch Op Processor = OS
// Completion Dispatcher = Proactor
// Completion Handler = HTPP_Handler
{
public:
void open (Socket_Stream *client)
{
// Initialize state for request
request_.state_ = INCOMPLETE;
 
// Store reference to client.
client_ = client;
 
// Initialize asynch read stream
stream_.open (*this, client_->handle (), proactor_);
 
// Start read asynchronously.
stream_.read (request_.buffer (),
request_.buffer_size ());
}
 
// This is called by the Proactor
// when the asynch read completes
void handle_read_stream(u_long bytes_transferred)
{
if (request_.enough_data(bytes_transferred))
parse_request ();
else
// Start reading asynchronously.
stream_.read (request_.buffer (),
 
request_.buffer_size ());
}
 
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 ());
 
// Start writing asynchronously.
stream_.write (file_.buffer (), file_.buffer_size ());
break;
 
// Client is storing a file
// at the server.
case HTTP_Request::PUT:
// ...
}
}
 
void handle_write_stream(u_long bytes_transferred)
{
if (file_.enough_data(bytes_transferred))
// Success....
else
// Start another asynchronous write
stream_.write (file_.buffer (), file_.buffer_size ());
}
 
private:
// Set at initialization.
Proactor *proactor_;
 
// Memory-mapped file_;
Mem_Map file_;
 
// Socket endpoint.
Socket_Stream *client_;
 
// HTTP Request holder
HTTP_Request request_;
 
// Used for Asynch I/O
Asynch_Stream stream_;
};
 
8.9 已知应用
 
下面是一些被q泛记蝲的前摄器的用:
 
Windows NT中的I/O完成端口Q?/b>Windows NT操作pȝ实现了前摄器模式。Windows NT支持多种Asynchronous OperationQ比如接受新|络q接、读写文件和socketQ以及通过|络q接传输文g。操作系l就是Asynchronous Operation Processor。操作结果在I/O完成端口Q它扮演Completion Dispatcher的角Ԍ上排队?/div>
 
异步I/O操作的UNIX AIO族:在有些实时POSIXq_上,前摄器模式是由aio API族[9]来实现的。这些OSҎ(gu)非常类g上面描述的Windows NT的特性。一个区别是UNIX信号可用于实现真正异步的Completion DispatcherQWindows NT API不是真正异步的)?/div>
 
ACE ProactorQ?/b>ACE自适配通信环境 [4]实现了前摄器lgQ它?yu)装Windows NT上的I/O完成端口Q以及POSIXq_上的aio API。ACE前摄器抽象提供Windows NT所支持的标准C API的OO接口。这一实现的源码可从ACE|站http://www.cs.wustl.edu/~schmidt/ACE.html获取?/div>
 
Windows NT中的异步q程调用QAsynchronous Procedure CallQ:有些pȝQ比如Windows NTQ支持异步过E调用(APCQ。APC是在特定U程的上下文中异步执行的函数。当APC被排队到U程Ӟpȝ发出软g中断。下一ơ线E被调度Ӟ它将q行该APC。操作系l所发出的APC被称?i>内核模式APC。应用所发出的APC被称?i>用户模式APC?/div>
 
8.10 相关模式
 
?-9演示与前摄器相关的模式?/div>
 
 
?-9 前摄器模式的相关模式
 
异步完成令牌QACTQ模式[8]通常与前摄器模式l合使用。当Asynchronous Operation完成Ӟ应用可能需要比单的通知更多的信息来适当地处理事件。异步完成o牌模式允许应用将状态高效地与Asynchronous Operation的完成相兌?/div>
前摄器模式还与观察者(ObserverQ模式[12]Q在其中Q当单个主题变动Ӟ相关对象也会自动更新Q有兟뀂在前摄器模式中Q当来自多个来源的事件发生时Q处理器被自动地通知。一般而言Q前摄器模式被用于异步地多个输入源多\分离l与它们相关联的事g处理器,而观察者通常仅与单个事g源相兌?/div>
前摄器模式可被认为是同步反应堆模式[5]的一U?i>异步?/i>变体。反应堆模式负责多个事g处理器的多\分离和分z;它们在可?i>同步地发?/i>操作而不会阻塞时被触发。相反,前摄器模式也支持多个事g处理器的多\分离和分z,但它们是?i>异步事g的完?/i>触发的?/div>
d对象QActive ObjectQ模式[13]使方法执行与Ҏ(gu)调用去耦合。前摄器模式也是cM的,因ؓAsynchronous Operation Processor代表应用的Proactive Initiator来执行操作。就是说Q两U模式都可用于实现Asynchronous Operation。前摄器模式常常用于替代d对象模式Q以使系lƈ发策略与U程模型去耦合?/div>
前摄器可被实Cؓ单体QSingletonQ[12]。这对于在异步应用中Q将事g多\分离和完成分zN中到单一的地Ҏ(gu)说是有用的?/div>
责Q链(Chain of ResponsibilityQCORQ模式[12]使事件处理器与事件源去耦合。在Proactive Initiator与Completion Handler的隔MQ前摄器模式也是cM的。但是,在COR中,事g源预先不知道哪一个处理器被执行Q如果有的话Q。在前摄器中QProactive Initiator完全知道目标处理器。但是,通过建立一个Completion HandlerQ它是由外部工厂动态配|的责Q铄入口Q,q两U模式可被结合在一P?/div>
 
8.11 l束?/b>
 
前摄器模式包含了一U强大的设计范式Q支持高性能q发应用的高效而灵zȝ事g分派{略。前摄器模式提供q发执行操作的性能助益Q而又不强q开发者用同步多U程或反应式~程?/div>
 
参考文?/b>
 
[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 ?5 Conference in Computer Communication Review, (Boston, MA, USA), pp. 299?14, 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?45, 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?38, 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?, September 1995.
 
附录A 可选实?/b>
 
本附录概q用于开发前摄器模式的可选实现的代码。下面,我们查用多U程的同步I/O和用单U程的反应式I/O?/div>
 
A.1 多个同步U程
 
下面的代码显C怎样使用U程池同步I/O来开发Web服务器。当客户q接到服务器Ӟ池中的一个线E接受连接,q调用HTTP_Handler中的openҎ(gu)。随后服务器同步C|络q接dh。当L作完成时Q客戯求随之被解析。在对GETh的响应中Q服务器Ҏ(gu)h文gq行内存映射Qƈ文件数据同步地写往客户。注意阻塞I/O是怎样使Web服务器能够遵?.2.1中所概述的步骤的?/div>
 
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 单线E反应式事g分派
 
下面的代码显C怎样反应堆模式用于开发Web服务器。当客户q接到服务器ӞHTTP_Handler::openҎ(gu)被调用。服务器登记I/O句柄和在|络句柄“读qA“时回调的对象(在此例中是this指针Q。然后服务器q回事g循环?/div>
当请求数据到达服务器Ӟreactor_回调HTTP_Handler::handle_inputҎ(gu)。客h据以非阻塞方式被d。如果有_的数据,客户hp解析。如果整个客戯求还没有到达Q应用就q回反应堆事件@环?/div>
在对GETh的响应中Q服务器Ҏ(gu)h的文件进行内存映;q在反应堆上登记Q以在网l连接变为“写qA”时被通知。当向连接写入数据不会阻塞调用线E时Qreactor_回调HTTP_Handler::handler_outputҎ(gu)。当所有数据都已发送给客户Ӟ|络q接被关闭?/div>
 
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 releas

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_;
};

本文转蝲至ACE开发者网?作者:Irfan Pyarali Tim Harrison


walkspeed 2007-02-27 21:17 发表评论
]]>ACE中网l通讯~程基本架构http://www.shnenglu.com/walkspeed/archive/2007/02/25/18969.htmlwalkspeedwalkspeedSun, 25 Feb 2007 11:30:00 GMThttp://www.shnenglu.com/walkspeed/archive/2007/02/25/18969.htmlhttp://www.shnenglu.com/walkspeed/comments/18969.htmlhttp://www.shnenglu.com/walkspeed/archive/2007/02/25/18969.html#Feedback5http://www.shnenglu.com/walkspeed/comments/commentRss/18969.htmlhttp://www.shnenglu.com/walkspeed/services/trackbacks/18969.html    ACE_INET_Addrc,包装了网l地址
    ACE_SOCK_Connectorc,扮演dq接角色Q发起通讯q接。连接到q端的服务?br />    ACE_SOCK_Acceptorc,扮演被动q接角色Q等待连接。等待远端客Lh?br />    ACE_SOCK_Streamc,扮演数据通讯角色Q发送和接收数据。完成客户与服务之间的通讯?br />   
    利用ACE库来开发网l通讯E序是很单的Q一个基本程序只用到以上提到的几个类Q就
可以完成一个基于客L、服务器端模型的|络应用的开发。开发者无需了解Socket在不同^
C的实玎ͼ记忆众多q相互关联的Socket APIs?/p>

    一下以一个Hello WorldE序为演C?br />   
    客户端程序。发送一个Hello World到远端的服务器,q接收服务器q回的信息,信?br />打印在屏q上?/p>

#include <iostream>
#include <string>

#include <ace/ACE.h>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>

int main( int argc, char* argv[] )
{
 ACE::init();//初始化ACE库,在windows下一定要

 std::string str = "hello world";

 //讄服务器地址
 //W一个参数是端口Q第二个是ip地址Q也可以是域名?br /> //可以先定义一个地址对象Q再用ACE_INET_Addr的set函数来设定?br /> //地址的配|很多,具体的参照文?br /> ACE_INET_Addr peer_addr( 5050, "127.0.0.1" );
 ACE_SOCK_Stream peer_stream;//定义一个通讯队Ş

 ACE_SOCK_Connector peer_connector;//定义一个主动连接对?br /> peer_connector.connect( peer_stream, peer_addr );//发v一个连?/p>

 peer_stream.send( str.c_str(), str.length() );//发送数据到服务?/p>

 str.erase();
 str.resize( sizeof( "hello world" ) );
 peer_stream.recv( (void*)str.c_str(), str.length() );//接收来自服务器的信息

 std::cout << "from server message : " << str << std::endl;

    ACE::fini();
 return 0;
}

    服务器端代码。接收一个远端的q接Q将接收到的信息打印在屏q上Qƈ接收到的信
息返回给客户端?br />#include <iostream>
#include <string>

#include <ace/ACE.h>
#include <ace/SOCK_Acceptor.h>
#include <ace/SOCK_Stream.h>

int main( int argc, char* argv[] )
{
 ACE::init();

 std::string str;
 str.resize( sizeof( "hello world" ) );

 //讄服务器地址
 ACE_INET_Addr peer_addr( 5050, "127.0.0.1" );

 ACE_SOCK_Stream peer_stream;
 
 //创徏被动q接角色对象
 ACE_SOCK_Acceptor peer_acceptor;
 //开启被动连接对象,对象绑定到一个地址?br /> peer_acceptor.open( peer_addr );

 //{待q接
 peer_acceptor.accept( peer_stream );

 //数据通讯
 peer_stream.recv( (void*)str.c_str(), str.length() );
 std::cout << "from client message : " << str << std::endl;
 peer_stream.send( str.c_str(), str.length() );

 ACE::fini();
 return 0;
}
××××以上代码需要ACE库才能运转×××?br />   
    利用ACE~程的基本框架?br />    客户?br />    1 创徏地址对象。(ACE_INET_AddrQ?br />    2 创徏dq接对象。(ACE_SOCK_ConnectorQ?br />    3 创徏数据通讯对象。(ACE_SOCK_StreamQ?br />    4 讄服务器地址。(ACE_INET_Addr::setQ?br />    5 数据通讯对象和地址作ؓ参数传给dq接对象Q发起主动连接(ACE_SOCK_Connector::connectQ?br />    6 利用通讯对象接收和发送数据。(ACE_SOCK_Stream::recv和ACE_SOCK_Stream::sendQ?br />   
    服务器端
    1 创徏地址对象。(ACE_INET_AddrQ?br />    2 创徏被动q接对象。(ACE_SOCK_ConnectorQ?br />    3 创徏数据通讯对象。(ACE_SOCK_StreamQ?br />    4 讄服务器地址。(ACE_INET_Addr::setQ?br />    5 地址作ؓ参数传给被动q接对象Q启动接ӞACE_SOCK_Acceptor::openQ?br />    6 数据通讯对象传给被动q接对象Q启动接Ӟ接受q接QACE_SOCK_Connector::acceptQ?br />    7 利用通讯对象接收和发送数据。(ACE_SOCK_Stream::recv和ACE_SOCK_Stream::sendQ?/p>

walkspeed 2007-02-25 19:30 发表评论
]]>
ACE中Socket IPC通讯包装cLhttp://www.shnenglu.com/walkspeed/archive/2007/02/24/18942.htmlwalkspeedwalkspeedSat, 24 Feb 2007 06:15:00 GMThttp://www.shnenglu.com/walkspeed/archive/2007/02/24/18942.htmlhttp://www.shnenglu.com/walkspeed/comments/18942.htmlhttp://www.shnenglu.com/walkspeed/archive/2007/02/24/18942.html#Feedback0http://www.shnenglu.com/walkspeed/comments/commentRss/18942.htmlhttp://www.shnenglu.com/walkspeed/services/trackbacks/18942.html o_ACE IPC.jpg

    ACE_IPC_SAPcLIPCcL的基c,装了句柄,提供了访问句柄的基本接口Q基本结?br />如下
class ACE_IPC_SAP
{
public:
  int enable (int value) const;
  int disable (int value) const;

  ACE_HANDLE get_handle (void) const;
  void set_handle (ACE_HANDLE handle);

protected:
  ACE_IPC_SAP (void);
  ~ACE_IPC_SAP (void);

private:
  ACE_HANDLE handle_;
};

    ACE_SOCKcL使用Socket的基c,所有用Socket通讯的类都从q个cL生。本cȝ?br />能包?br />    1 创徏和销毁Socket句柄
    2 获取本地和远端的|络地址
    3 讄和读取Socket选项?br />基本l构如下
class ACE_SOCK : public ACE_IPC_SAP
{
public:
  //讄Socket的属性,包装了setsockoptpȝ函数
  int set_option (int level,
                  int option,
                  void *optval,
                  int optlen) const;
  //获取Socket的属性,包装了getsockoptpȝ函数
  int get_option (int level,
                  int option,
                  void *optval,
                  int *optlen) const;
  //获得本地地址
  int get_local_addr (ACE_Addr &) const;
  //获取q端地址
  int get_remote_addr (ACE_Addr &) const;
  //关闭Socket
  int close (void);
  //打开一个SocketQ没有Qos
  int open (int type,
            int protocol_family,
            int protocol,
            int reuse_addr);
  //打开一个SocketQ有Qos
  int open (int type,
            int protocol_family,
            int protocol,
            ACE_Protocol_Info *protocolinfo,
            ACE_SOCK_GROUP g,
            u_long flags,
            int reuse_addr);

protected:
  ACE_SOCK (int type,
            int protocol_family,
            int protocol = 0,
            int reuse_addr = 0);
  ACE_SOCK (int type,
            int protocol_family,
            int protocol,
            ACE_Protocol_Info *protocolinfo,
            ACE_SOCK_GROUP g,
            u_long flags,
            int reuse_addr);
  ACE_SOCK (void);
  ~ACE_SOCK (void);
};

    ACE_SOCK_IOc,包装了Socket数据通讯的基本方法。本cL供的功能
    1 支持数据的发送和接收
    2 支持分散L?br />    3 支持集中写操?br />    4 支持dQ非dQ定?I/O操作
基本l构如下
class ACE_SOCK_IO : public ACE_SOCK
{
public:
  ACE_SOCK_IO (void);
  ~ACE_SOCK_IO (void);

  //接收数据
  ssize_t recv (void *buf,
                size_t n,
                const ACE_Time_Value *timeout = 0) const;
  //分散L?br />  ssize_t recv (iovec iov[],
                size_t n,
                const ACE_Time_Value *timeout = 0) const;
  //发送数据            ?
  ssize_t send (const void *buf,
                size_t n,
                const ACE_Time_Value *timeout = 0) const;
  //集中写操?br />  ssize_t send (const iovec iov[],
                size_t n,
                const ACE_Time_Value *timeout = 0) const;
};

    ACE_SOCK_Streamc,l承ACE_SOCK_IOcR在ACE_SOCK_IOcL供的功能上,d了发?br />和接收刚好n个字节的能力。基本结构如?br />class ACE_Export ACE_SOCK_Stream : public ACE_SOCK_IO
{
public:
  ACE_SOCK_Stream (void);
  ACE_SOCK_Stream (ACE_HANDLE h);
  ~ACE_SOCK_Stream (void);
 
  //刚好dn个字节的数据
  ssize_t recv_n (void *buf,
                  size_t len,
                  const ACE_Time_Value *timeout = 0,
                  size_t *bytes_transferred = 0) const;
  //分散d好n个字节操?br />  ssize_t recvv_n (iovec iov[],
                   int iovcnt,
                   const ACE_Time_Value *timeout = 0,
                   size_t *bytes_transferred = 0) const;
  //刚好发送n个字节的数据
  ssize_t send_n (const void *buf,
                  size_t len,
                  const ACE_Time_Value *timeout = 0,
                  size_t *bytes_transferred = 0) const;
  //集中写刚好n个字节操?br />  ssize_t sendv_n (const iovec iov[],
                   int iovcnt,
                   const ACE_Time_Value *timeout = 0,
                   size_t *bytes_transferred = 0) const;

  int close_reader (void);
  int close_writer (void);

  int close (void);

  typedef ACE_INET_Addr PEER_ADDR;
};

    ACE_SOCK_AcceptorcL一个工厂类Q用来被动生一个新的通讯端点。提供如下能?br />    1 接收对等端的q接
    2 q接可以通过d、非d或定时方式接受?br />基本l构如下
class ACE_Export ACE_SOCK_Acceptor : public ACE_SOCK
{
public:

  ACE_SOCK_Acceptor (void);
  ACE_SOCK_Acceptor (const ACE_Addr &local_sap,
                     int reuse_addr = 0,
                     int protocol_family = PF_UNSPEC,
                     int backlog = ACE_DEFAULT_BACKLOG,
                     int protocol = 0);
  ~ACE_SOCK_Acceptor (void);

  //打开一个监?br />  int open (const ACE_Addr &local_sap,
            int reuse_addr = 0,
            int protocol_family = PF_UNSPEC,
            int backlog = ACE_DEFAULT_BACKLOG,
            int protocol = 0);

  int close (void);
  //接受一个对{端的连接,产生一个通讯
  int accept (ACE_SOCK_Stream &new_stream,
              ACE_Addr *remote_addr = 0,
              ACE_Time_Value *timeout = 0,
              int restart = 1,
              int reset_new_handle = 0) const;
};

    ACE_SOCK_ConnectorcL一个工厂类Q用来主动徏立一个新的通讯端。提供的功能如下
    1 发v一个到对等接受者的q接Qƈ在连接后产生一个通讯对象
    2 q接可以通过d、非d或定时方式发?br />基本l构如下
class ACE_SOCK_Connector
{
public:
  ACE_SOCK_Connector (void);
  ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream,
                      const ACE_Addr &remote_sap,
                      const ACE_Time_Value *timeout = 0,
                      const ACE_Addr &local_sap = ACE_Addr::sap_any,
                      int reuse_addr = 0,
                      int flags = 0,
                      int perms = 0,
                      int protocol = 0);

  //发v一个连?br />  int connect (ACE_SOCK_Stream &new_stream,
               const ACE_Addr &remote_sap,
               const ACE_Time_Value *timeout = 0,
               const ACE_Addr &local_sap = ACE_Addr::sap_any,
               int reuse_addr = 0,
               int flags = 0,
               int perms = 0,
               int protocol = 0);

  ~ACE_SOCK_Connector (void);

  int complete (ACE_SOCK_Stream &new_stream,
                ACE_Addr *remote_sap = 0,
                const ACE_Time_Value *timeout = 0);
};

    以上的类l构是简化的Q以H出重点功能。要完全了解每个c,看源代码?/p>

walkspeed 2007-02-24 14:15 发表评论
]]>
ACE_WFMO_Reactor多\分配d部分结http://www.shnenglu.com/walkspeed/archive/2007/02/22/18906.htmlwalkspeedwalkspeedThu, 22 Feb 2007 03:46:00 GMThttp://www.shnenglu.com/walkspeed/archive/2007/02/22/18906.htmlhttp://www.shnenglu.com/walkspeed/comments/18906.htmlhttp://www.shnenglu.com/walkspeed/archive/2007/02/22/18906.html#Feedback0http://www.shnenglu.com/walkspeed/comments/commentRss/18906.htmlhttp://www.shnenglu.com/walkspeed/services/trackbacks/18906.html    多\分配的入口函数handle_eventsQ在框架的实现接口类中定?br />    多\分配的主体实现函数event_handling,在ACE_WFMO_Reactor中定义,?br />实现代码如下
int ACE_WFMO_Reactor::event_handling (ACE_Time_Value *max_wait_time,
                                      int alertable)
{
  int result = 0;
 
  do
  {
      //{待在句柄集上发生的事g
      //wait_for_multiple_events的具体实现是使用
      //WaitForMultipleObjectsEx函数
      DWORD wait_status = this->wait_for_multiple_events (timeout,
                                                          alertable);
      //分发事g
      result = this->safe_dispatch (wait_status);
  }while (result == 0);

  return result;
}

    分发的主体函数是dispatch_handles,在ACE_WFMO_Reactor中定义,伪实?br />代码如下
int ACE_WFMO_Reactor::dispatch_handles (DWORD wait_status)
{
  DWORD dispatch_slot = 0;

  //zd的句柄L
  DWORD max_handlep1 = this->handler_rep_.max_handlep1 ();

  //查找要分发的句柄的烦?br />  for (int number_of_handlers_dispatched = 1;;++number_of_handlers_dispatched)
  {
      //计算有事件发生,要分发的句柄索引
      dispatch_slot += wait_status - WAIT_OBJECT_0;
      //分发l相应的事g处理对象
      if (this->dispatch_handler (dispatch_slot, max_handlep1) == -1)
        return -1;

      ++dispatch_slot;

      if (dispatch_slot >= max_handlep1)
        return number_of_handlers_dispatched;//分发了几个事?/p>

      //查剩下的句柄中有没有有事件发生的
      wait_status = this->poll_remaining_handles (dispatch_slot);
      switch (wait_status)
      {
        case WAIT_FAILED: // Failure.
          ACE_OS::set_errno_to_last_error ();
          /* FALLTHRU */
        case WAIT_TIMEOUT:
          // There are no more handles ready, we can return.
          return number_of_handlers_dispatched;//分发了几个事?br />      }
  }
}

    扑ֈ具体事g处理对象M函数complex_dispatch_hander,在ACE_WFMO_Reactor
中定义,Z码如?br />int ACE_WFMO_Reactor::complex_dispatch_handler (DWORD slot,
                                                ACE_HANDLE event_handle)
{
  //扑ֈ当前的分发的信息
  ACE_WFMO_Reactor_Handler_Repository::Current_Info &current_info =
    this->handler_rep_.current_info ()[slot];

  WSANETWORKEVENTS events;
  ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;
  if (::WSAEnumNetworkEvents ((SOCKET) current_info.io_handle_,
                              event_handle,
                              &events) == SOCKET_ERROR)
    problems = ACE_Event_Handler::ALL_EVENTS_MASK;
  else
  {
      //发生的事件于要检的事g是否相同Q相同就分发
      events.lNetworkEvents &= current_info.network_events_;
      while (events.lNetworkEvents != 0)
      {
          ACE_Event_Handler *event_handler = current_info.event_handler_;

          //调用事g处理对象Q进行事件处?br />          problems |= this->upcall (current_info.event_handler_,
                                    current_info.io_handle_,
                                    events);

          if (this->handler_rep_.scheduled_for_deletion (slot))
            break;
      }
  }

  return 0;
}



walkspeed 2007-02-22 11:46 发表评论
]]>
ACE_WFMO_Reactor对事件的{待和分发的M代码的整?/title><link>http://www.shnenglu.com/walkspeed/archive/2007/02/22/18904.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Thu, 22 Feb 2007 02:54:00 GMT</pubDate><guid>http://www.shnenglu.com/walkspeed/archive/2007/02/22/18904.html</guid><wfw:comment>http://www.shnenglu.com/walkspeed/comments/18904.html</wfw:comment><comments>http://www.shnenglu.com/walkspeed/archive/2007/02/22/18904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/walkspeed/comments/commentRss/18904.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/walkspeed/services/trackbacks/18904.html</trackback:ping><description><![CDATA[ <p>1<br />int ACE_WFMO_Reactor::handle_events (ACE_Time_Value &how_long)<br />{<br />  return this->event_handling (&how_long, FALSE);<br />}</p> <p>2<br />// Waits for and dispatches all events.  Returns -1 on error, 0 if<br />// max_wait_time expired, or the number of events that were dispatched.<br />int ACE_WFMO_Reactor::event_handling (ACE_Time_Value *max_wait_time,<br />                                      int alertable)<br />{<br />  ACE_TRACE ("ACE_WFMO_Reactor::event_handling");</p> <p>  // Make sure we are not closed<br />  if (!this->open_for_business_ || this->deactivated_)<br />      return -1;</p> <p>  // Stash the current time -- the destructor of this object will<br />  // automatically compute how much time elapsed since this method was<br />  // called.<br />  ACE_Countdown_Time countdown (max_wait_time);</p> <p>  int result;<br />  <br />  do<br />  {<br />      // Check to see if it is ok to enter ::WaitForMultipleObjects<br />      // This will acquire <this->lock_> on success On failure, the<br />      // lock will not be acquired<br />      <br />      result = this->ok_to_wait (max_wait_time, alertable);<br />      if (result != 1)<br />        return result;</p> <p>      // Increment the number of active threads<br />      ++this->active_threads_;</p> <p>      // Release the <lock_><br />      this->lock_.release ();</p> <p>      // Update the countdown to reflect time waiting to play with the<br />      // mut and event.<br />      <br />      countdown.update ();</p> <p>      // Calculate timeout<br />      int timeout = this->calculate_timeout (max_wait_time);</p> <p>      // Wait for event to happen<br />      DWORD wait_status = this->wait_for_multiple_events (timeout,<br />                                                          alertable);</p> <p>      // Upcall<br />      result = this->safe_dispatch (wait_status);<br />      if (0 == result)<br />      {<br />          // wait_for_multiple_events timed out without dispatching<br />          // anything.  Because of rounding and conversion errors and<br />          // such, it could be that the wait loop timed out, but<br />          // the timer queue said it wasn't quite ready to expire a<br />          // timer. In this case, max_wait_time won't have quite been<br />          // reduced to 0, and we need to go around again. If max_wait_time<br />          // is all the way to 0, just return, as the entire time the<br />          // caller wanted to wait has been used up.<br />          countdown.update ();     // Reflect time waiting for events<br />          <br />          if (0 == max_wait_time || max_wait_time->usec () == 0)<br />            break;<br />      }<br />  }while (result == 0);</p> <p>  return result;<br />}</p> <p>3<br />int ACE_WFMO_Reactor::safe_dispatch (DWORD wait_status)<br />{<br />  int result = -1;<br />  ACE_SEH_TRY<br />  {<br />      result = this->dispatch (wait_status);<br />  }<br />  ACE_SEH_FINALLY<br />  {<br />      this->update_state ();<br />  }</p> <p>  return result;<br />}</p> <p>4<br />int ACE_WFMO_Reactor::dispatch (DWORD wait_status)<br />{<br />  int handlers_dispatched = 0;</p> <p>  // Expire timers<br />  handlers_dispatched += this->expire_timers ();</p> <p>  switch (wait_status)<br />  {<br />  case WAIT_FAILED: // Failure.<br />      ACE_OS::set_errno_to_last_error ();<br />      return -1;</p> <p>  case WAIT_TIMEOUT: // Timeout.<br />      errno = ETIME;<br />      return handlers_dispatched;</p> <p>  default:  // Dispatch.<br />      // We'll let dispatch worry about abandoned mutes.<br />      handlers_dispatched += this->dispatch_handles (wait_status);<br />      return handlers_dispatched;<br />  }<br />}</p> <p>5<br />// Dispatches any active handles from <handles_[slot]> to<br />// <handles_[max_handlep1_]>, polling through our handle set looking<br />// for active handles.</p> <p>int ACE_WFMO_Reactor::dispatch_handles (DWORD wait_status)<br />{<br />  // dispatch_slot is the absolute slot.  Only += is used to<br />  // increment it.<br />  DWORD dispatch_slot = 0;</p> <p>  // Cache this value, this is the absolute value.<br />  DWORD max_handlep1 = this->handler_rep_.max_handlep1 ();</p> <p>  // nCount starts off at <max_handlep1>, this is a transient count of<br />  // handles last waited on.<br />  DWORD nCount = max_handlep1;</p> <p>  for (int number_of_handlers_dispatched = 1;;++number_of_handlers_dispatched)<br />  {<br />      const bool ok = (wait_status >= WAIT_OBJECT_0 && wait_status <= (WAIT_OBJECT_0 + nCount));</p> <p>      if (ok)<br />        dispatch_slot += wait_status - WAIT_OBJECT_0;<br />      else<br />        // Otherwise, a handle was abandoned.<br />        dispatch_slot += wait_status - WAIT_ABANDONED_0;</p> <p>      // Dispatch handler<br />      if (this->dispatch_handler (dispatch_slot, max_handlep1) == -1)<br />        return -1;</p> <p>      // Increment slot<br />      ++dispatch_slot;</p> <p>      // We're done.<br />      if (dispatch_slot >= max_handlep1)<br />        return number_of_handlers_dispatched;</p> <p>      // Readjust nCount<br />      nCount = max_handlep1 - dispatch_slot;</p> <p>      // Check the remaining handles<br />      wait_status = this->poll_remaining_handles (dispatch_slot);<br />      switch (wait_status)<br />      {<br />        case WAIT_FAILED: // Failure.<br />          ACE_OS::set_errno_to_last_error ();<br />          /* FALLTHRU */<br />        case WAIT_TIMEOUT:<br />          // There are no more handles ready, we can return.<br />          return number_of_handlers_dispatched;<br />      }<br />  }<br />}</p> <p>6<br />int ACE_WFMO_Reactor::dispatch_handler (DWORD slot,<br />                                        DWORD max_handlep1)<br />{<br />  // Check if there are window messages that need to be dispatched<br />  if (slot == max_handlep1)<br />    return this->dispatch_window_messages ();</p> <p>  // Dispatch the handler if it has not been scheduled for deletion.<br />  // Note that this is a very week test if there are multiple threads<br />  // dispatching this slot as no locks are held here. Generally, you<br />  // do not want to do something like deleting the this pointer in<br />  // handle_close() if you have registered multiple times and there is<br />  // more than one thread in WFMO_Reactor->handle_events().<br />  else if (!this->handler_rep_.scheduled_for_deletion (slot))<br />  {<br />      ACE_HANDLE event_handle = *(this->handler_rep_.handles () + slot);</p> <p>      if (this->handler_rep_.current_info ()[slot].io_entry_)<br />        return this->complex_dispatch_handler (slot,<br />                                               event_handle);<br />      else<br />        return this->simple_dispatch_handler (slot,<br />                                              event_handle);<br />  }<br />  else<br />    // The handle was scheduled for deletion, so we will skip it.<br />    return 0;<br />}</p> <p>7<br />int ACE_WFMO_Reactor::complex_dispatch_handler (DWORD slot,<br />                                                ACE_HANDLE event_handle)<br />{<br />  // This dispatch is used for I/O entires.</p> <p>  ACE_WFMO_Reactor_Handler_Repository::Current_Info &current_info =<br />    this->handler_rep_.current_info ()[slot];</p> <p>  WSANETWORKEVENTS events;<br />  ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;<br />  if (::WSAEnumNetworkEvents ((SOCKET) current_info.io_handle_,<br />                              event_handle,<br />                              &events) == SOCKET_ERROR)<br />    problems = ACE_Event_Handler::ALL_EVENTS_MASK;<br />  else<br />  {<br />      // Prepare for upcalls. Clear the bits from <events> representing<br />      // events the handler is not interested in. If there are any left,<br />      // do the upcall(s). upcall will replace events.lNetworkEvents<br />      // with bits representing any functions that requested a repeat<br />      // callback before checking handles again. In this case, continue<br />      // to call back unless the handler is unregistered as a result of<br />      // one of the upcalls. The way this is written, the upcalls will<br />      // keep being done even if one or more upcalls reported problems.<br />      // In practice this may turn out not so good, but let's see. If any<br />      // problems, please notify Steve Huston <<a href="mailto:shuston@riverace.com">shuston@riverace.com</a>><br />      // before or after you change this code.<br />      events.lNetworkEvents &= current_info.network_events_;<br />      while (events.lNetworkEvents != 0)<br />      {<br />          ACE_Event_Handler *event_handler = current_info.event_handler_;</p> <p>          int reference_counting_required =<br />            event_handler->reference_counting_policy ().value () ==<br />            ACE_Event_Handler::Reference_Counting_Policy::ENABLED;</p> <p>          // Call add_reference() if needed.<br />          if (reference_counting_required)<br />          {<br />              event_handler->add_reference ();<br />          }</p> <p>          // Upcall<br />          problems |= this->upcall (current_info.event_handler_,<br />                                    current_info.io_handle_,<br />                                    events);</p> <p>          // Call remove_reference() if needed.<br />          if (reference_counting_required)<br />          {<br />              event_handler->remove_reference ();<br />          }</p> <p>          if (this->handler_rep_.scheduled_for_deletion (slot))<br />            break;<br />      }<br />  }</p> <p>  if (problems != ACE_Event_Handler::NULL_MASK<br />      && !this->handler_rep_.scheduled_for_deletion (slot)  )<br />    this->handler_rep_.unbind (event_handle, problems);</p> <p>  return 0;<br />}</p> <p>8<br />ACE_Reactor_Mask ACE_WFMO_Reactor::upcall (ACE_Event_Handler *event_handler,<br />                                           ACE_HANDLE io_handle,<br />                                           WSANETWORKEVENTS &events)<br />{<br />  // This method figures out what exactly has happened to the socket<br />  // and then calls appropriate methods.<br />  ACE_Reactor_Mask problems = ACE_Event_Handler::NULL_MASK;</p> <p>  // Go through the events and do the indicated upcalls. If the handler<br />  // doesn't want to be called back, clear the bit for that event.<br />  // At the end, set the bits back to <events> to request a repeat call.</p> <p>  long actual_events = events.lNetworkEvents;<br />  int action;</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_WRITE))<br />  {<br />      action = event_handler->handle_output (io_handle);<br />      if (action <= 0)<br />      {<br />          ACE_CLR_BITS (actual_events, FD_WRITE);<br />          if (action == -1)<br />            ACE_SET_BITS (problems, ACE_Event_Handler::WRITE_MASK);<br />      }<br />  }</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_CONNECT))<br />  {<br />      if (events.iErrorCode[FD_CONNECT_BIT] == 0)<br />      {<br />          // Successful connect<br />          action = event_handler->handle_output (io_handle);<br />          if (action <= 0)<br />          {<br />              ACE_CLR_BITS (actual_events, FD_CONNECT);<br />              if (action == -1)<br />                ACE_SET_BITS (problems, ACE_Event_Handler::CONNECT_MASK);<br />          }<br />      }<br />      // Unsuccessful connect<br />      else<br />      {<br />          action = event_handler->handle_input (io_handle);<br />          if (action <= 0)<br />          {<br />              ACE_CLR_BITS (actual_events, FD_CONNECT);<br />              if (action == -1)<br />                ACE_SET_BITS (problems, ACE_Event_Handler::CONNECT_MASK);<br />          }<br />      }<br />  }</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_OOB))<br />  {<br />      action = event_handler->handle_exception (io_handle);<br />      if (action <= 0)<br />      {<br />          ACE_CLR_BITS (actual_events, FD_OOB);<br />          if (action == -1)<br />            ACE_SET_BITS (problems, ACE_Event_Handler::EXCEPT_MASK);<br />      }<br />  }</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_READ))<br />  {<br />      action = event_handler->handle_input (io_handle);<br />      if (action <= 0)<br />      {<br />          ACE_CLR_BITS (actual_events, FD_READ);<br />          if (action == -1)<br />            ACE_SET_BITS (problems, ACE_Event_Handler::READ_MASK);<br />      }<br />  }</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_CLOSE)<br />      && ACE_BIT_DISABLED (problems, ACE_Event_Handler::READ_MASK))<br />  {<br />      action = event_handler->handle_input (io_handle);<br />      if (action <= 0)<br />      {<br />          ACE_CLR_BITS (actual_events, FD_CLOSE);<br />          if (action == -1)<br />            ACE_SET_BITS (problems, ACE_Event_Handler::READ_MASK);<br />      }<br />  }</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_ACCEPT))<br />  {<br />      action = event_handler->handle_input (io_handle);<br />      if (action <= 0)<br />      {<br />          ACE_CLR_BITS (actual_events, FD_ACCEPT);<br />          if (action == -1)<br />            ACE_SET_BITS (problems, ACE_Event_Handler::ACCEPT_MASK);<br />      }<br />  }</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_QOS))<br />  {<br />      action = event_handler->handle_qos (io_handle);<br />      if (action <= 0)<br />      {<br />          ACE_CLR_BITS (actual_events, FD_QOS);<br />          if (action == -1)<br />            ACE_SET_BITS (problems, ACE_Event_Handler::QOS_MASK);<br />      }<br />  }</p> <p>  if (ACE_BIT_ENABLED (actual_events, FD_GROUP_QOS))<br />  {<br />      action = event_handler->handle_group_qos (io_handle);<br />      if (action <= 0)<br />      {<br />          ACE_CLR_BITS (actual_events, FD_GROUP_QOS);<br />          if (action == -1)<br />            ACE_SET_BITS (problems, ACE_Event_Handler::GROUP_QOS_MASK);<br />      }<br />  }</p> <p>  events.lNetworkEvents = actual_events;<br />  return problems;<br />}</p> <img src ="http://www.shnenglu.com/walkspeed/aggbug/18904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/walkspeed/" target="_blank">walkspeed</a> 2007-02-22 10:54 <a href="http://www.shnenglu.com/walkspeed/archive/2007/02/22/18904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE框架的三大部?/title><link>http://www.shnenglu.com/walkspeed/archive/2007/02/20/18876.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Tue, 20 Feb 2007 04:28:00 GMT</pubDate><guid>http://www.shnenglu.com/walkspeed/archive/2007/02/20/18876.html</guid><wfw:comment>http://www.shnenglu.com/walkspeed/comments/18876.html</wfw:comment><comments>http://www.shnenglu.com/walkspeed/archive/2007/02/20/18876.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/walkspeed/comments/commentRss/18876.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/walkspeed/services/trackbacks/18876.html</trackback:ping><description><![CDATA[        ACEq个开源项目的代码的量是很大的。对于系l编E、网l编E是非常的有用,但是对其介绍的书和资料是非常的少。要想了解和很好的用,必要自己ȝ源代码了。(好在q有三本书,库中的事例还是比较的多)<br />        ACE库中的代码大体可以分Z大部?br />        1  OS AdaptationQ操作系l适配Q部分。这部分主要是屏蔽各操作pȝ的API的不同,系l调用接口统一到CQ+函数的接口,以实现^台的可移植?br />        2  C++ Wrapper FacadeQC++外包Q部分。这部分主要是将怺兌的操作和数据l构装到C++cMQ提供统一的接口。提供强cd的检,降低不必要的认ؓ错误。利用C++多态、承等能力QŞ成一个架构,使本地的、远端的操作l一在一个相同接口和使用{略下?br />        3  FrameworkQ框Ӟ部分。ؓ一l相关的应用提供可复用的架构。开发者在定了应用后Q选择可用的架构开发应用程序,不用考虑q_和底层机制。快速的开发?br />        W一部分面对大量的底层的l节Q而且目标是^台的ULQ如果对q_的移植感兴趣的兄弟姐妹可以看看。一般情况下没什么看的必要?br />        W二部分和第三部分对我们的应用和学习如何利用C++来设计程序非常的有h(hun)|要多看。细心揣摩,特别是配上设计的问题Q宏观的和微观的Q?img src ="http://www.shnenglu.com/walkspeed/aggbug/18876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/walkspeed/" target="_blank">walkspeed</a> 2007-02-20 12:28 <a href="http://www.shnenglu.com/walkspeed/archive/2007/02/20/18876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.yb121.com.cn" target="_blank">ɫɫۺϾþҹҹ</a>| <a href="http://www.3ponline.com.cn" target="_blank">99þþƷѹۿ</a>| <a href="http://www.xinkecheng.net.cn" target="_blank">Ļþ</a>| <a href="http://www.malmoarts.cn" target="_blank">þùƷHDAV</a>| <a href="http://www.zjslzy.com.cn" target="_blank">avþþƷ</a>| <a href="http://www.air-ticket.cn" target="_blank">2020þþƷۺһ</a>| <a href="http://www.njglqw.org.cn" target="_blank">þþƷƵ</a>| <a href="http://www.88354.com.cn" target="_blank">þþƷ99ɫĻ</a>| <a href="http://www.adddi.cn" target="_blank">ھƷþþþþĻ</a>| <a href="http://www.hskx.org.cn" target="_blank">þþþƷѹĻ</a>| <a href="http://www.piaozen.cn" target="_blank">þþƷŷ</a>| <a href="http://www.zgsmkf.cn" target="_blank">wwwɫ˾þþƷ</a>| <a href="http://www.bjxisaa.cn" target="_blank">ƷŮþþþAV</a>| <a href="http://www.91368.com.cn" target="_blank">Ѿþþþþ</a>| <a href="http://www.yizhuyuan.cn" target="_blank">þþƷ99þ㽶</a>| <a href="http://www.e9920.cn" target="_blank">ɫþˬˬƬaV</a>| <a href="http://www.pz851.cn" target="_blank">޾Ʒһۺ99þ</a>| <a href="http://www.pobk.cn" target="_blank">vĻþ 뾫ƷþɪӰ </a>| <a href="http://www.songyufen.cn" target="_blank">ɫþˬˬƬAV</a>| <a href="http://www.e-li.cn" target="_blank">޾Ʒtvþþþ</a>| <a href="http://www.ssc629.cn" target="_blank">99þ㽶߿</a>| <a href="http://www.z718.cn" target="_blank">þþþһvr</a>| <a href="http://www.j16dr.cn" target="_blank">91Ʒ91þþþþ</a>| <a href="http://www.vltr.cn" target="_blank">þ99ƷþþþþҰ</a>| <a href="http://www.fengbiaochem.com.cn" target="_blank">þۺ¶þü</a>| <a href="http://www.9dqmu.cn" target="_blank">ŮþþŮ</a>| <a href="http://www.bekin.com.cn" target="_blank">Aݺݾþɫ</a>| <a href="http://www.pyqf.net.cn" target="_blank">þþ޾Ʒһ</a>| <a href="http://www.xxysw.com.cn" target="_blank">˾þô߽</a>| <a href="http://www.caregps.cn" target="_blank">ƷҹþøƬ</a>| <a href="http://www.greendaily.cn" target="_blank">þӰԺþ㽶߿ۿ</a>| <a href="http://www.520chuanqi.cn" target="_blank">ɫþþþþۺ</a>| <a href="http://www.iview-inc.com.cn" target="_blank">99ƷȾþ޶</a>| <a href="http://www.fcsyx.cn" target="_blank">޾Ʒþþwww</a>| <a href="http://www.babaishu.cn" target="_blank">Ʒþһ</a>| <a href="http://www.0795fcw.cn" target="_blank">þþƷƵһ</a>| <a href="http://www.cq321.cn" target="_blank">þþùƷ</a>| <a href="http://www.airesou.cn" target="_blank">þþþùƷ</a>| <a href="http://www.8812345.com.cn" target="_blank">޹þþþƷ</a>| <a href="http://www.jinshengsuliao.cn" target="_blank">ھƷþþþþ鶹</a>| <a href="http://www.ssc905.cn" target="_blank">þþþþAv뾫Ʒר</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>