Completion instead of readiness
The proactor pattern is the asynchronous cousin of the reactor. Where a reactor waits for a resource to become ready and then performs the IO itself, a proactor submits the full IO operation up front and waits for it to complete. The kernel does the transfer, then notifies a completion handler.
The flow
- An initiator starts an asynchronous operation and supplies a buffer
- The kernel or an async IO service performs the entire read or write
- On completion an event is posted to a completion dispatcher
- The dispatcher invokes the completion handler with the finished result
The handler runs with the data already in the buffer. There is no read step inside the handler, because the read already happened.
Reactor versus proactor
- Reactor handlers do the IO after a readiness signal
- Proactor handlers process results after a completion signal
- Proactor maps naturally onto Windows completion ports and Linux io uring
The proactor shines where the platform offers true asynchronous IO, since the application never blocks on the transfer at all.
Key idea
The proactor submits a full IO operation and lets the kernel complete it, then dispatches a completion handler that processes the already finished result.