NAME
ACE_Proactor -
An abstraction for Proactive I/O.
SYNOPSIS
#include <ace/Proactor.h>
class ACE_Proactor : public ACE_Event_Handler
{
public:
ACE_Proactor (size_t number_of_threads = 0);
int close (void);
virtual int handle_signal (
int,
siginfo_t * = 0,
ucontext_t * = 0
);
virtual ACE_HANDLE get_handle (void) const;
virtual int handle_events (ACE_Time_Value *how_long = 0);
virtual int handle_events (ACE_Time_Value &how_long);
virtual int initiate (
ACE_Event_Handler *handler,
ACE_Reactor_Mask mask = ACE_Event_Handler::WRITE_MASK,
ACE_Message_Block *msg = 0,
ACE_Overlapped_File *file = 0
);
virtual int schedule_timer (
ACE_Event_Handler *,
const void *arg,
const ACE_Time_Value &delta,
const ACE_Time_Value &interval = ACE_Time_Value::zero
);
virtual int cancel_timer (ACE_Event_Handler *handler);
virtual int cancel_timer (int timer_id, const void **arg = 0);
protected:
ACE_Timer_Queue timer_queue_;
ACE_Time_Value timer_skew_;
virtual int initiate (ACE_Overlapped_IO *overlapped);
int dispatch (
ACE_Overlapped_IO *overlapped,
u_long bytes_transfered
);
ACE_HANDLE completion_port_;
size_t number_of_threads_;
ACE_HANDLE global_handle_;
};
DESCRIPTION
The ACE_Proactor encapsulates Win32 overlapped I/O. The ACE_Proactor
is also an ACE_Event_Handler which can be registered with the
ACE_ReactorEx, as follows:
int
main ()
{
// ...
// Register Proactor with ReactorEx.
ACE_Service_Config::reactorEx ()-register_handler
(ACE_Service_Config::proactor ());
// Demultiplex all ReactorEx and Proactor events from a single
// thread.
ACE_Service_Config::run_reactorEx_event_loop ();
return 42;
}
This makes it possible to seemlessly integrate the ACE_Proactor (which
handles only overlapped I/O) with other forms of Win32 HANDLE-based
synchronization (e.g., Mutexes, Semaphores, Threads, Processes, etc.).
Initialization and termination methods.
ACE_Proactor (size_t number_of_threads = 0);
Initialize a proactor and give it the number of threads to allow
to run concurrently (note that we don't spawn the threads, the NT
kernel does).
int close (void);
Event demultiplexing hooks inherited from Event_Handler.
virtual int handle_signal (int, siginfo_t * = 0, ucontext_t * = 0);
Called back when used in the context of the ReactorEx.
virtual ACE_HANDLE get_handle (void) const;
Returns the underlying Win32 Event HANDLE that is used to
integrate I/O completion ports with the ReactorEx.
Event loop methods.
virtual int handle_events (ACE_Time_Value *how_long = 0);
virtual int handle_events (ACE_Time_Value &how_long);
Main event loop driver that blocks for -how_long- before
returning (will return earlier if I/O or signal events occur).
Note that -how_long- can be 0, in which case this method blocks
until I/O events or signals occur. handle_events just blocks
on GetQueuedCompletionStatus at completion_port_. When I/O
completions arrive, it calls back the Event_Handler associated
with completed I/O operation. Returns 0 if -how_long- elapses
before an event occurs, 1 when if an event occured, and -1 on
failure.
Communication method.
virtual int initiate (
ACE_Event_Handler *handler,
ACE_Reactor_Mask mask = ACE_Event_Handler::WRITE_MASK,
ACE_Message_Block *msg = 0,
ACE_Overlapped_File *file = 0
);
Invoke proactive I/O on handler. If msg == 0, the Proactor
will call handler::get_message to obtain an ACE_Message_Block
to send/recv according to mask. If mask ==
ACE_Event_Handler::WRITE_MASK, the Proactor calls WriteFile using
the msg and Event_Handler::get_handle. Returns 1 if the operation
succeeded immediately, 0 if the operation is pending (in which
case the handler will be called back), and -1 if an error
occurred. file represents the offset into the file to initiate
the operation with. When using the proactor for overlapped file
I/O, the user is responsible for maintaining the pointer to the
file. If you perform multiple initiates with the same or no
File_Pointer value, initiate will fill in the same file data into
multiple Message_Blocks. file is ignored for network I/O or if
file == 0. If file != 0 it is updated (via lseek) respective to
the operation initiated.
Timer management.
virtual int schedule_timer (
ACE_Event_Handler *,
const void *arg,
const ACE_Time_Value &delta,
const ACE_Time_Value &interval = ACE_Time_Value::zero
);
Schedule an Event_Handler that will expire after delay amount
of time. If it expires then arg is passed in as the value to
the Event_Handler's handle_timeout callback method. If
interval is != to ACE_Time_Value::zero then it is used to
reschedule the Event_Handler automatically. This method
returns a timer handle that uniquely identifies the
Event_Handler in an internal list. This timer handle can be
used to cancel an Event_Handler before it expires. The
cancellation ensures that timer_ids are unique up to values of
greater than 2 billion timers. As long as timers don't stay
around longer than this there should be no problems with
accidentally deleting the wrong timer.
virtual int cancel_timer (ACE_Event_Handler *handler);
Cancel all Event_Handlers that match the address of
Event_Handler.
virtual int cancel_timer (int timer_id, const void **arg = 0);
Cancel the single ACE_Event_Handler that matches the timer_id
value (which was returned from the schedule method). If arg is
non-NULL then it will be set to point to the ``magic cookie''
argument passed in when the Event_Handler was registered. This
makes it possible to free up the memory and avoid memory leaks.
AUTHOR
Doug Schmidt (schmidt@cs.wustl.edu),
Tim Harrison (harrison@cs.wustl.edu), and
Irfan Pyarali (ip1@cs.wustl.edu).
LIBRARY
ace