// -*- C++ -*- //============================================================================= /** * @file Svc_Handler.h * * $Id$ * * @author Douglas Schmidt * @author Irfan Pyarali */ //============================================================================= #ifndef ACE_SVC_HANDLER_H #define ACE_SVC_HANDLER_H #include /**/ "ace/pre.h" // Forward decls. class ACE_Connection_Recycling_Strategy; #include "ace/Synch_Options.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Task.h" #include "ace/Service_Config.h" #include "ace/Recyclable.h" /** * @class ACE_Svc_Handler * * @brief Defines the interface for a service that exchanges data with * its connected peer. * * This class provides a well-defined interface that the * Acceptor and Connector pattern factories use as their target. * Typically, client applications will subclass ACE_Svc_Handler * and do all the interesting work in the subclass. One thing * that the ACE_Svc_Handler does contain is a PEER_STREAM * endpoint that is initialized by an ACE_Acceptor or * ACE_Connector when a connection is established successfully. * This endpoint is used to exchange data between a * ACE_Svc_Handler and the peer it is connected with. */ template class ACE_Svc_Handler : public ACE_Task { public: // Useful STL-style traits. typedef ACE_PEER_STREAM_ADDR addr_type; typedef ACE_PEER_STREAM stream_type; /** * Constructor initializes the @a thr_mgr and @a mq by passing them * down to the ACE_Task base class. The @a reactor is passed to * the ACE_Event_Handler. */ ACE_Svc_Handler (ACE_Thread_Manager *thr_mgr = 0, ACE_Message_Queue *mq = 0, ACE_Reactor *reactor = ACE_Reactor::instance ()); /// Destructor. virtual ~ACE_Svc_Handler (void); /// Activate the client handler. This is typically called by the /// ACE_Acceptor or ACE_Connector. virtual int open (void * = 0); /** * Object termination hook -- application-specific cleanup code goes * here. This function is called by the idle() function if the object * does not have a ACE_Connection_Recycling_Strategy associated with it. * Also, due to this class's derivation from ACE_Task, close() is * also called when a thread activated with this object exits. See * ACE_Task::close() for further details. The default action of this * function is to call handle_close() with the default arguments. */ virtual int close (u_long flags = 0); /** * Call this method if you want to recycling the @c Svc_Handler * instead of closing it. If the object does not have a recycler, * it will be closed. */ virtual int idle (u_long flags = 0); /** * Call this method if you want to get/set the state of the * @c Svc_Handler. If the object does not have a recycler, this call * will have no effect (and the accessor will return * ACE_RECYCLABLE_UNKNOWN). */ virtual ACE_Recyclable_State recycle_state (void) const; virtual int recycle_state (ACE_Recyclable_State new_state); /** * When the svc_handle is no longer needed around as a hint, call * this method. In addition, reset @c *act_holder to zero if * @a act_holder != 0. */ virtual void cleanup_hint (void **act_holder = 0); // = Dynamic linking hooks. /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int init (int argc, ACE_TCHAR *argv[]); /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int fini (void); /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int info (ACE_TCHAR **info_string, size_t length) const; // = Demultiplexing hooks. /** * Perform termination activities on the SVC_HANDLER. The default * behavior is to close down the (to avoid descriptor leaks) * and to this object (to avoid memory leaks)! If you * don't want this behavior make sure you override this method... */ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); /// Default behavior when timeouts occur is to close down the /// by calling . virtual int handle_timeout (const ACE_Time_Value &time, const void *); /// Get the underlying handle associated with the . virtual ACE_HANDLE get_handle (void) const; /// Set the underlying handle associated with the . virtual void set_handle (ACE_HANDLE); /// Returns the underlying PEER_STREAM. Used by /// and factories ACE_PEER_STREAM &peer (void) const; /// Overloaded new operator. This method unobtrusively records if a /// is allocated dynamically, which allows it to clean /// itself up correctly whether or not it's allocated statically or /// dynamically. void *operator new (size_t n); #if defined (ACE_HAS_NEW_NOTHROW) /// Overloaded new operator, nothrow_t variant. Unobtrusively records if a /// is allocated dynamically, which allows it to clean /// itself up correctly whether or not it's allocated statically or /// dynamically. void *operator new (size_t n, const ACE_nothrow_t&) throw(); #endif /// This operator permits "placement new" on a per-object basis. void * operator new (size_t n, void *p); /** * Call this to free up dynamically allocated * (otherwise you will get memory leaks). In general, you should * call this method rather than since this method knows * whether or not the object was allocated dynamically, and can act * accordingly (i.e., deleting it if it was allocated dynamically). */ virtual void destroy (void); /** * This really should be private so that users are forced to call * . Unfortunately, the C++ standard doesn't allow there * to be a public new and a private delete. It is a bad idea to * call this method directly, so use instead, unless you * know for sure that you've allocated the object dynamically. */ void operator delete (void *); #if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE) /** * This operator is necessary to complement the class-specific * operator new above. Unfortunately, it's not portable to all C++ * compilers... */ void operator delete (void *, void *); #endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */ /// Close down the descriptor and unregister from the Reactor void shutdown (void); /// Dump the state of an object. void dump (void) const; public: // = The following methods are not suppose to be public. // Because friendship is *not* inherited in C++, these methods have // to be public. // = Accessors to set/get the connection recycler. /// Set the recycler and the that is used during /// purging and caching. virtual void recycler (ACE_Connection_Recycling_Strategy *recycler, const void *recycling_act); /// Get the recycler. virtual ACE_Connection_Recycling_Strategy *recycler (void) const; /// Get the recycling act. virtual const void *recycling_act (void) const; /** * Upcall made by the recycler when it is about to recycle the * connection. This gives the object a chance to prepare itself for * recycling. Return 0 if the object is ready for recycling, -1 on * failures. */ virtual int recycle (void * = 0); protected: /// Maintain connection with client. ACE_PEER_STREAM peer_; /// Have we been dynamically created? int dynamic_; /// Keeps track of whether we are in the process of closing (required /// to avoid circular calls to ). char closing_; /// Pointer to the connection recycler. ACE_Connection_Recycling_Strategy *recycler_; /// Asynchronous Completion Token (ACT) to be used to when talking to /// the recycler. const void *recycling_act_; }; /** * @class ACE_Buffered_Svc_Handler * * @brief Defines the interface for a service that exchanges data with * its connected peer and supports buffering. * * The buffering feature makes it possible to queue up * in an until (1) the * queue is "full" or (2) a period of time elapses, at which * point the queue is "flushed" via to the peer. */ template class ACE_Buffered_Svc_Handler : public ACE_Svc_Handler { public: // = Initialization and termination methods. /** * Constructor initializes the and by passing them * down to the base class. The is passed to * the . The and * are used to determine at what point to flush * the . By default, there's no buffering at all. The * value is interpreted to be in a unit that's * relative to the current time returned by . */ ACE_Buffered_Svc_Handler (ACE_Thread_Manager *thr_mgr = 0, ACE_Message_Queue *mq = 0, ACE_Reactor *reactor = ACE_Reactor::instance (), size_t max_buffer_size = 0, ACE_Time_Value *relative_timeout = 0); /// Destructor, which calls . virtual ~ACE_Buffered_Svc_Handler (void); /** * Insert the chain rooted at * into the with the designated . The * method will be called if this causes the number of * bytes to exceed the maximum buffer size or if the timeout period * has elapsed. */ virtual int put (ACE_Message_Block *message_block, ACE_Time_Value *timeout = 0); /// Flush the , which writes all the queued /// s to the . virtual int flush (void); /// This method is not currently implemented -- this is where the /// integration with the would occur. virtual int handle_timeout (const ACE_Time_Value &time, const void *); /// Dump the state of an object. void dump (void) const; protected: /// Implement the flush operation on the , which /// writes all the queued s to the . /// Assumes that the caller holds the lock. virtual int flush_i (void); /// Maximum size the can be before we have to flush /// the buffer. size_t maximum_buffer_size_; /// Current size in bytes of the contents. size_t current_buffer_size_; /// Timeout value used to control when the buffer is flushed. ACE_Time_Value next_timeout_; /// Interval of the timeout. ACE_Time_Value interval_; /// Timeout pointer. ACE_Time_Value *timeoutp_; }; #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) #include "ace/Svc_Handler.cpp" #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation ("Svc_Handler.cpp") #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ #include /**/ "ace/post.h" #endif /* ACE_SVC_HANDLER_H */