0%

[boost.asio] 2.proactor I/0设计模式:单线程并发

Boost.Asio 库为支持同步和异步操作。异步支持基于proactor设计模式[POSA2]。与同步或Reactor方法相比,这种方法的优点和缺点概述如下。 ## Proactor 与 Reactor - Proactor和Reactor都是并发编程中的设计模式 - Proactor用于异步IO,而Reactor用于同步IO, 关键区别在于 何时IO - Reactor:非阻塞同步网络模型,关心就绪事件, 可以理解为:来了事件我通知你,你来处理,如epoll_wait - Proactor:异步网络模型,关心完成事件,可以理解为:来了事件我来处理,处理完了我通知你。

Proactor 与 Boost.Asio#

Proactor设计模式#

  • 异步操作(Asynchronous Operation) 定义异步执行的操作,例如 异步读或在套接字上写入
  • 异步操作处理器(Asynchronous Operation Processor) 执行异步操作,并在操作完成时对completion event queue中的事件进行排队。从高层次的角度来看,像reactive_socket_service这样的内部服务是异步操作处理器。
  • 完成事件队列(Completion Event Queue) 缓冲完成事件,直到它们被Asynchronous Event Demultiplexer移出队列。
  • 完成处理程序(Completion Handler) 处理异步操作的结果。这些是函数对象,通常使用boost::bind创建
  • 异步事件多路分配器(Asynchronous Event Demultiplexer) 阻塞并等待完成事件队列上发生的事件,并将完成的事件返回其调用者。
  • 前摄器(Proactor) 调用Asynchronous Event Demultiplexer将事件出列,并分派与事件关联的Completion Handler程序(即调用函数对象)。这个抽象由io_context类表示。
  • 发起者(Initiator) 启动异步操作的应用程序特定代码。启动器通过高级接口(如basic_stream_socket)与异步操作处理器进行交互,而高级接口又 委托给 (如reactive_socket_service)等服务

基于Reactor的实现#

在许多平台上,Boost.Asio 在Reactor(如select, epoll或kqueue)中实现Proactor设计模式,如下所示:

  • 异步操作处理器(Asynchronous Operation Processor) 使用select, epoll或kqueue实现的Reactor。当Reactor指示资源已准备好执行操作时,处理器将执行异步操作,并将关联的completion handler程序入列(enqueue)完成事件队列。
  • 完成事件队列(Completion Event Queue) 完成处理程序(即函数对象)的链表。
  • 异步事件多路分配器(Asynchronous Event Demultiplexer) 这是通过等待事件或条件变量实现的,直到完成处理程序在完成事件队列中可用。

使用 Windows 重叠(Overlapped)I/O 实现#

在 Windows NT、2000 和 XP 上,Boost.Asio 利用重叠 I/O 提供Proactor模式的高效实现。此实现方法对应于Proactor设计模式,如下所示:

  • 异步操作处理器(Asynchronous Operation Processor) 这是由操作系统实现的。操作通过调用Overlapped函数(如AcceptEx)启动。
  • 完成事件队列(Completion Event Queue) 这由操作系统实现,并关联到 I/O 完成端口。每个io_context实例都有一个 I/O 完成端口。
  • 异步事件多路分配器(Asynchronous Event Demultiplexer) 由 Boost.Asio 调用,使事件及其关联的完成处理程序出列。

缺点#

  • 程序复杂性(Program complexity)。 由于操作启动和完成之间的 时间和空间的分离,使用异步机制开发应用程序更加困难。由于控制流的倒置,应用程序也可能更难调试
  • 内存使用情况(Memory usage)。 在读取或写入操作期间必须提交缓冲区空间,此操作可能会无限期地继续,并且每个并发操作都需要单独的缓冲区。另一方面,在套接字准备好读取或写入之前,Reactor模式不需要缓冲空间。

reference#

  1. 如何深刻理解Reactor和Proactor?
  2. The Proactor Design Pattern: Concurrency Without Threads