/dep/acelite/ace/TP_Reactor.h
C Header | 320 lines | 103 code | 59 blank | 158 comment | 0 complexity | f85145bb82eddea839ce7b28b3279f82 MD5 | raw file
- // -*- C++ -*-
- //=============================================================================
- /**
- * @file TP_Reactor.h
- *
- * $Id: TP_Reactor.h 82723 2008-09-16 09:35:44Z johnnyw $
- *
- * The ACE_TP_Reactor (aka, Thread Pool Reactor) uses the
- * Leader/Followers pattern to demultiplex events among a pool of
- * threads. When using a thread pool reactor, an application
- * pre-spawns a fixed number of threads. When these threads
- * invoke the ACE_TP_Reactor's handle_events() method, one thread
- * will become the leader and wait for an event. The other
- * follower threads will queue up waiting for their turn to become
- * the leader. When an event occurs, the leader will pick a
- * follower to become the leader and go on to handle the event.
- * The consequence of using ACE_TP_Reactor is the amortization of
- * the costs used to create threads. The context switching cost
- * will also reduce. Moreover, the total resources used by
- * threads are bounded because there are a fixed number of threads.
- *
- * @author Irfan Pyarali <irfan@cs.wustl.edu>
- * @author Nanbor Wang <nanbor@cs.wustl.edu>
- */
- //=============================================================================
- #ifndef ACE_TP_REACTOR_H
- #define ACE_TP_REACTOR_H
- #include /**/ "ace/pre.h"
- #include "ace/Select_Reactor.h"
- #include "ace/Timer_Queue.h" /* Simple forward decl won't work... */
- #if !defined (ACE_LACKS_PRAGMA_ONCE)
- # pragma once
- #endif /* ACE_LACKS_PRAGMA_ONCE */
- ACE_BEGIN_VERSIONED_NAMESPACE_DECL
- /**
- * @class ACE_EH_Dispatch_Info
- *
- * @brief This structure contains information of the activated event
- * handler.
- */
- class ACE_EH_Dispatch_Info
- {
- public:
- ACE_EH_Dispatch_Info (void);
- void set (ACE_HANDLE handle,
- ACE_Event_Handler *event_handler,
- ACE_Reactor_Mask mask,
- ACE_EH_PTMF callback);
- bool dispatch (void) const;
- ACE_HANDLE handle_;
- ACE_Event_Handler *event_handler_;
- ACE_Reactor_Mask mask_;
- ACE_EH_PTMF callback_;
- int resume_flag_;
- bool reference_counting_required_;
- private:
- bool dispatch_;
- // Disallow copying and assignment.
- ACE_EH_Dispatch_Info (const ACE_EH_Dispatch_Info &);
- ACE_EH_Dispatch_Info &operator= (const ACE_EH_Dispatch_Info &);
- };
- /**
- * @class ACE_TP_Token_Guard
- *
- * @brief A helper class that helps grabbing, releasing and waiting
- * on tokens for a thread that tries calling handle_events ().
- *
- * In short, this class will be owned by one thread by creating on the
- * stack. This class gives the status of the ownership of the token
- * and manages the ownership
- */
- class ACE_TP_Token_Guard
- {
- public:
- /// Constructor that will grab the token for us
- ACE_TP_Token_Guard (ACE_Select_Reactor_Token &token);
- /// Destructor. This will release the token if it hasnt been
- /// released till this point
- ~ACE_TP_Token_Guard (void);
- /// Release the token ..
- void release_token (void);
- /// Returns whether the thread that created this object ownes the
- /// token or not.
- bool is_owner (void);
- /// A helper method that grabs the token for us, after which the
- /// thread that owns that can do some actual work.
- int acquire_read_token (ACE_Time_Value *max_wait_time = 0);
- /**
- * A helper method that grabs the token for us, after which the
- * thread that owns that can do some actual work. This differs from
- * acquire_read_token() as it uses acquire () to get the token instead of
- * acquire_read ()
- */
- int acquire_token (ACE_Time_Value *max_wait_time = 0);
- private:
- // Disallow default construction.
- ACE_TP_Token_Guard (void);
- // Disallow copying and assignment.
- ACE_TP_Token_Guard (const ACE_TP_Token_Guard &);
- ACE_TP_Token_Guard &operator= (const ACE_TP_Token_Guard &);
- private:
- /// The Select Reactor token.
- ACE_Select_Reactor_Token &token_;
- /// Flag that indicate whether the thread that created this object
- /// owns the token or not. A value of false indicates that this class
- /// hasnt got the token (and hence the thread) and a value of true
- /// vice-versa.
- bool owner_;
- };
- /**
- * @class ACE_TP_Reactor
- *
- * @brief Specialization of ACE_Select_Reactor to support thread-pool
- * based event dispatching.
- *
- * One of the shortcomings of the ACE_Select_Reactor is that it
- * does not support a thread pool-based event dispatching model,
- * similar to the one in ACE_WFMO_Reactor. In ACE_Select_Reactor, only
- * thread can call handle_events() at any given time. ACE_TP_Reactor
- * removes this short-coming.
- *
- * ACE_TP_Reactor is a specialization of ACE_Select_Reactor to support
- * thread pool-based event dispatching. This reactor takes advantage
- * of the fact that events reported by @c select() are persistent if not
- * acted upon immediately. It works by remembering the event handler
- * which was just activated, suspending it for further I/O activities,
- * releasing the internal lock (so that another thread can start waiting
- * in the event loop) and then dispatching the event's handler outside the
- * scope of the reactor lock. After the event handler has been dispatched
- * the event handler is resumed for further I/O activity.
- *
- * This reactor implementation is best suited for situations when the
- * callbacks to event handlers can take arbitrarily long and/or a number
- * of threads are available to run the event loop. Note that I/O-processing
- * callback code in event handlers (e.g. handle_input()) does not have to
- * be modified or made thread-safe for this reactor. This is because
- * before an I/O event is dispatched to an event handler, the handler is
- * suspended; it is resumed by the reactor after the upcall completes.
- * Therefore, multiple I/O events will not be made to one event handler
- * multiple threads simultaneously. This suspend/resume protection does not
- * apply to either timers scheduled with the reactor or to notifications
- * requested via the reactor. When using timers and/or notifications you
- * must provide proper protection for your class in the context of multiple
- * threads.
- */
- class ACE_Export ACE_TP_Reactor : public ACE_Select_Reactor
- {
- public:
- /// Initialize ACE_TP_Reactor with the default size.
- ACE_TP_Reactor (ACE_Sig_Handler * = 0,
- ACE_Timer_Queue * = 0,
- bool mask_signals = true,
- int s_queue = ACE_Select_Reactor_Token::FIFO);
- /**
- * Initialize the ACE_TP_Reactor to manage
- * @a max_number_of_handles. If @a restart is non-0 then the
- * ACE_Reactor's @c handle_events() method will be restarted
- * automatically when @c EINTR occurs. If @a sh or
- * @a tq are non-0 they are used as the signal handler and
- * timer queue, respectively.
- */
- ACE_TP_Reactor (size_t max_number_of_handles,
- bool restart = false,
- ACE_Sig_Handler *sh = 0,
- ACE_Timer_Queue *tq = 0,
- bool mask_signals = true,
- int s_queue = ACE_Select_Reactor_Token::FIFO);
- /**
- * This event loop driver that blocks for @a max_wait_time before
- * returning. It will return earlier if timer events, I/O events,
- * or signal events occur. Note that @a max_wait_time can be 0, in
- * which case this method blocks indefinitely until events occur.
- *
- * @a max_wait_time is decremented to reflect how much time this call
- * took. For instance, if a time value of 3 seconds is passed to
- * handle_events and an event occurs after 2 seconds,
- * @a max_wait_time will equal 1 second. This can be used if an
- * application wishes to handle events for some fixed amount of
- * time.
- *
- * @return The total number of events that were dispatched; 0 if the
- * @a max_wait_time elapsed without dispatching any handlers, or -1
- * if an error occurs (check @c errno for more information).
- */
- virtual int handle_events (ACE_Time_Value *max_wait_time = 0);
- virtual int handle_events (ACE_Time_Value &max_wait_time);
- /// Does the reactor allow the application to resume the handle on
- /// its own ie. can it pass on the control of handle resumption to
- /// the application. The TP reactor has can allow applications to
- /// resume handles. So return a positive value.
- virtual int resumable_handler (void);
- /// Called from handle events
- static void no_op_sleep_hook (void *);
- /// The ACE_TP_Reactor implementation does not have a single owner thread.
- /// Attempts to set the owner explicitly are ignored. The reported owner
- /// thread is the current Leader in the pattern.
- virtual int owner (ACE_thread_t n_id, ACE_thread_t *o_id = 0);
- /// Return the thread ID of the current Leader.
- virtual int owner (ACE_thread_t *t_id);
- /// Declare the dynamic allocation hooks.
- ACE_ALLOC_HOOK_DECLARE;
- protected:
- // = Internal methods that do the actual work.
- /// Template method from the base class.
- virtual void clear_dispatch_mask (ACE_HANDLE handle,
- ACE_Reactor_Mask mask);
- /// Dispatch just 1 signal, timer, notification handlers
- int dispatch_i (ACE_Time_Value *max_wait_time,
- ACE_TP_Token_Guard &guard);
- /// Get the event that needs dispatching. It could be either a
- /// signal, timer, notification handlers or return possibly 1 I/O
- /// handler for dispatching. In the most common use case, this would
- /// return 1 I/O handler for dispatching
- int get_event_for_dispatching (ACE_Time_Value *max_wait_time);
- #if 0
- // @Ciju
- // signal handling isn't in a production state yet.
- // Commenting it out for now.
- /// Method to handle signals
- /// @note It is just busted at this point in time.
- int handle_signals (int &event_count,
- ACE_TP_Token_Guard &g);
- #endif // #if 0
- /// Handle timer events
- int handle_timer_events (int &event_count,
- ACE_TP_Token_Guard &g);
- /// Handle notify events
- int handle_notify_events (int &event_count,
- ACE_TP_Token_Guard &g);
- /// handle socket events
- int handle_socket_events (int &event_count,
- ACE_TP_Token_Guard &g);
- /// This method shouldn't get called.
- virtual void notify_handle (ACE_HANDLE handle,
- ACE_Reactor_Mask mask,
- ACE_Handle_Set &,
- ACE_Event_Handler *eh,
- ACE_EH_PTMF callback);
- private:
- /// Get the handle of the notify pipe from the ready set if there is
- /// an event in the notify pipe.
- ACE_HANDLE get_notify_handle (void);
- /// Get socket event dispatch information.
- int get_socket_event_info (ACE_EH_Dispatch_Info &info);
- /// Notify the appropriate <callback> in the context of the <eh>
- /// associated with <handle> that a particular event has occurred.
- int dispatch_socket_event (ACE_EH_Dispatch_Info &dispatch_info);
- /// Clear the @a handle from the read_set
- void clear_handle_read_set (ACE_HANDLE handle);
- int post_process_socket_event (ACE_EH_Dispatch_Info &dispatch_info,int status);
- private:
- /// Deny access since member-wise won't work...
- ACE_TP_Reactor (const ACE_TP_Reactor &);
- ACE_TP_Reactor &operator = (const ACE_TP_Reactor &);
- };
- ACE_END_VERSIONED_NAMESPACE_DECL
- #if defined (__ACE_INLINE__)
- #include "ace/TP_Reactor.inl"
- #endif /* __ACE_INLINE__ */
- #include /**/ "ace/post.h"
- #endif /* ACE_TP_REACTOR_H */