Proactor and reactor pattern _ literacy for continuing Concurrent System Design

Source: Internet
Author: User

Proactor and reactor pattern _ literacy for continuing Concurrent System Design

6.6.2008

Kevin lynx

Proactor and reactor
All are the design patterns in concurrent programming. In my opinion, they are all used to dispatch/detach Io operation events. The so-called
Io events are Io operations such as read/write. "Distribution/separation" means to notify the upper-layer module of independent Io events. The two modes are different.
That is, proactor is used for asynchronous Io, while reactor is used for Synchronous Io.

Extract some key things:

"
Two patterns that involve event demultiplexors are called reactor and proactor [1]. The reactor patterns

Involve synchronous I/O, whereas the proactor pattern involves asynchronous I/O.
"

The general model of the two modes can be understood in the following text:

"
An example will help you understand the difference between reactor and proactor. We will focus on the read

Operation here, as the write implementation is similar. Here's a read in reactor:

* An event handler declares interest in I/O events that indicate readiness for read on a particle socket;
* The Event demultiplexor waits for events;
* An event comes in and wakes-up the demultiplexor, And the demultiplexor callthe appropriate handler;

* The event handler performs the actual read operation, handles the data read, declares renewed interest in

I/O events, and returns control to the dispatcher.

By comparison, here is a read operation in proactor (true async ):

* A handler initiates an asynchronous read operation (note: the OS must support asynchronous I/O). In this

Case, the handler does not care about I/O readiness events, but is instead registers interest in processing ing

Completion events;
* The Event demultiplexor waits until the operation is completed;
* While the event demultiplexor waits, the OS executes the read operation in a parallel kernel thread, puts

Data into a user-defined buffer, and notifies the event demultiplexor that the read is complete;
* The Event demultiplexor callthe appropriate handler;

* The event handler handles the data from user defined buffer, starts a new Asynchronous Operation, and returns
Control to the event demultiplexor.

"

It can be seen that the similarities between the two modes are the Event Notification for an IO event (that is, to tell a module that this Io operation can be performed or has been completed ). In the structure
The two are also similar: demultiplexor is responsible for submitting Io operations (asynchronous), querying whether the device can operate (synchronous), and then callback handler when the conditions are met.
The difference is that, in asynchronous mode (proactor), when the callback handler, it indicates that the IO operation has been completed; when the synchronization is performed (Reactor), it indicates that
The IO Device can perform an operation (can read or can write). handler starts to submit the operation at this time.

Write a simple reactor using the select model, which is roughly as follows:

///


Class
Handler

{

Public
:


Virtual
 
Void
Onread ()
=
 
0
;


Virtual
 
Void
Onwrite ()
=
 
0
;


Virtual
 
Void
Onaccept ()
=
 
0
;

}

;


Class
Dispatch

{

Public
:


Void
Poll ()


{


//
Add FD in the set.


//



//
Poll every FD



Int
C
=
Select (
0
,
&
Read_fd,
&
Write_fd,
0
,
0
);


If
(C
>
 
0
)


{


For
Each FD
In
The read_fd_set


{
If
FD can read

_ Handler
->
Onread ();


If
FD can accept

_ Handler
->
Onaccept ();

}

 



For
Each FD
In
The write_fd_set


{


If
FD can write

_ Handler
->
Onwrite ();

}



}



}

 



Void
Sethandler (Handler
*
_ H)


{

_ Handler
=
_ H;

}

 


Private
:

Handler
*
_ Handler;

}

;


///
Application


Class
Myhandler:
Public
Handler

{

Public
:


Void
Onread ()


{

}

 



Void
Onwrite ()


{

}

 



Void
Onaccept ()


{

}



}

;


I found a more formal proactor mode document on the Internet.
It provides an overall UML class diagram, which is comprehensive:

Based on this figure, I wrote an example code:

Class
Asyioprocessor

{

Public
:


Void
Do_read ()


{


//

Send read operation to OS


//
Read Io finished. And dispatch notification


_ Proactor
->
Dispatch_read ();

}

 


Private
:

Proactor
*
_ Proactor;

}

;


Class
Proactor

{

Public
:


Void
Dispatch_read ()


{

_ Handlermgr
->
Onread ();

}

 


Private
:

Handlermanager
*
_ Handlermgr;

}

;


Class
Handlermanager

{

Public
:

Typedef STD: List
<
Handler
*>
Handlerlist;


Public
:


Void
Onread ()


{


//
Every y all the handlers.


STD: for_each (_ handlers. Begin (), _ handlers. End (), onread );

}

 


Private
:

Handlerlist
*
_ Handlers;

}

;


Class
Handler

{

Public
:


Virtual
 
Void
Onread ()
=
 
0
;

}

;


//
Application level handler.


Class
Myhandler:
Public
Handler

{

Public
:


Void
Onread ()


{


//
 


}



}

;


A reactor can be converted to a proactor through some deformation. In some systems that do not support asynchronous Io, the underlying implementation can also be hidden, facilitating the compilation of cross-platform
Code. We only need to encapsulate the code for Synchronous I/O operations in dispatch (that is, demultiplexor). At the upper layer, the user submits his/her own buffer to this layer,
This layer checks that the device can operate, unlike the original callback handler, but starts Io operations, then puts the operation results in the user buffer (read), and then
Callback handler. In this way, the upper-layer handler is like a proactor. For detailed techniques, see this article.
.

In fact, as far as the design model is concerned, I personally think that a certain model is not completely fixed. It cannot be said that there will certainly be a class in a certain mode, between classes
The relationship is definitely like this. In the actual process of writing a program, we seldom implement a certain mode. We can only say that the mode will give you more and better architecture solutions.

Recently I am reading spserver code. I am a little jealous of the pattern mentioned by others in various concurrent systems. Know what the leader follower mode is.
,
Reactor, proactor, and multiplexing are increasingly clear about the network library.

Recently, I have done some outrageous things, writing the legendary byte stream encoding, and implementing it using templates not only maintains the scalability, but also writes a lot less code. In consideration of efficiency,
Write a static array container (actually, It is template <typename _ TP, STD: size_t size> class static_array {_ TP _ CON [size]),
The iterator is added and follows the STL standard. It can be combined with generic algorithm of STL to help you feel good about yourself. After the Basic module is set up
Is it true that I plan to rewrite my verification server with my network module? In another tool written to the company, it is really annoying.
More and more repeated codes simply write a few macros and implement automatic generation of code: D.

The pursuit of elegant code is really a kind of hobby. = |


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.