/* -*- C++ -*- */ // $Id$ // ============================================================================ // // = LIBRARY // ace // // = FILENAME // Connector.h // // = AUTHOR // Doug Schmidt // // ============================================================================ #ifndef ACE_CONNECTOR_H #define ACE_CONNECTOR_H #include "ace/Service_Config.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Service_Object.h" #include "ace/Map_Manager.h" #include "ace/Svc_Handler.h" #include "ace/Strategies.h" template class ACE_Svc_Tuple { // = TITLE // Holds the ACE_Svc_Handler and its argument and // until an asynchronous connection completes. // // = DESCRIPTION // This is a no-brainer... public: // = Initialization methods. ACE_Svc_Tuple (SVC_HANDLER *, ACE_HANDLE, const void * = 0, long timer_id = -1); // = Get SVC_HANDLER. SVC_HANDLER *svc_handler (void); // = Get/set handle. ACE_HANDLE handle (void); // Get handle. void handle (ACE_HANDLE); // Set handle. // = Get/set argument. const void *arg (void); // Get argument. void arg (const void *); // Set argument. // = Set/get timer cancellation handle. long cancellation_id (void); // Get cancellation id. void cancellation_id (long timer_id); // Set cancellation id. void dump (void) const; // Dump the state of an object. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. private: SVC_HANDLER *svc_handler_; // Associated SVC_HANDLER. ACE_HANDLE handle_; // IPC that we are trying to connect. const void *arg_; // Associated argument. long cancellation_id_; // Associated cancellation id. }; template class ACE_Connector : public ACE_Service_Object { // = TITLE // Generic factory for actively connecting clients and creating // service handlers (SVC_HANDLERs). // // = DESCRIPTION // Implements the strategy for actively establishing connections // with clients. An ACE_Connector is parameterized by concrete // types that conform to the interfaces of PEER_CONNECTOR and // SVC_HANDLER. The PEER_CONNECTOR is instantiated with a // transport mechanism that passively establishes connections. // The SVC_HANDLER is instantiated with a concrete type that // performs the application-specific service. An ACE_Connector // inherits from ACE_Service_Object, which in turn inherits from // ACE_Event_Handler. This enables the ACE_Reactor to dispatch // the ACE_Connector's handle_output method when connections // complete asynchronously. The handle_output method performs // the connector's active connection establishment and service // activation strategy. public: // = Initialization and termination methods. // typedef ACE_TYPENAME ACE_PEER_CONNECTOR_ADDR PEER_ADDR; #if defined (ACE_HAS_TYPENAME_KEYWORD) typedef ACE_PEER_CONNECTOR_ADDR ACE_PEER_ADDR_TYPEDEF; #endif /* ACE_HAS_TYPENAME_KEYWORD */ ACE_Connector (ACE_Reactor *r = ACE_Reactor::instance (), int flags = 0); // Initialize a connector. indicates how 's // should be initialized prior to being activated. Right now, the // only flag that is processed is , which enabled // non-blocking I/O on the when it is opened. virtual int open (ACE_Reactor *r = ACE_Reactor::instance (), int flags = 0); // Initialize a connector. indicates how 's // should be initialized prior to being activated. Right now, the // only flag that is processed is , which enabled // non-blocking I/O on the when it is opened. virtual ~ACE_Connector (void); // Shutdown a connector and release resources. // = Connection establishment methods. virtual int connect (SVC_HANDLER *&svc_handler, const ACE_PEER_CONNECTOR_ADDR &remote_addr, const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, const ACE_PEER_CONNECTOR_ADDR &local_addr = (ACE_PEER_CONNECTOR_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY, int reuse_addr = 0, int flags = O_RDWR, int perms = 0); // Initiate connection of to peer at // using . If the caller wants to designate the // selected they can (and can also insist that the // be reused by passing a value == // 1). and can be used to pass any flags that are // needed to perform specific operations such as opening a file // within connect with certain permissions. If the connection fails // the hook on the will be called // automatically to prevent resource leaks. virtual int connect (SVC_HANDLER *&svc_handler_hint, SVC_HANDLER *&svc_handler, const ACE_PEER_CONNECTOR_ADDR &remote_addr, const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, const ACE_PEER_CONNECTOR_ADDR &local_addr = (ACE_PEER_CONNECTOR_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY, int reuse_addr = 0, int flags = O_RDWR, int perms = 0); // This is a variation on the previous method. On cached // connectors the variable can be used as a hint // for future lookups. Since this variable is modified in the // context of the internal cache its use is thread-safe. But the // actual svc_handler for the current connection is returned in the // second parameter . If the connection fails the // hook on the will be called automatically to // prevent resource leaks. virtual int connect_n (size_t n, SVC_HANDLER *svc_handlers[], ACE_PEER_CONNECTOR_ADDR remote_addrs[], ASYS_TCHAR *failed_svc_handlers = 0, const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults); // Initiate connection of to peers at // using . Returns -1 if failure // occurs and 0 otherwise. If is non-NULL, a // 1 is placed in the corresponding index of // for each that failed to connect, else a 0 is // placed in that index. virtual int cancel (SVC_HANDLER *svc_handler); // Cancel a that was started asynchronously. Note that // this is the only case when the Connector does not actively close // the . It is left up to the caller of to // decide the fate of the . virtual int close (void); // Close down the Connector void dump (void) const; // Dump the state of an object. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. protected: // = Helpful typedefs. typedef ACE_Svc_Tuple AST; typedef ACE_Map_Manager *, ACE_SYNCH_RW_MUTEX> MAP_MANAGER; typedef ACE_Map_Iterator *, ACE_SYNCH_RW_MUTEX> MAP_ITERATOR; typedef ACE_Map_Entry *> MAP_ENTRY; // = The following two methods define the Connector's strategies for // creating, connecting, and activating SVC_HANDLER's, respectively. virtual int make_svc_handler (SVC_HANDLER *&sh); // Bridge method for creating a SVC_HANDLER. The default is to // create a new SVC_HANDLER only if == 0, else is // unchanged. However, subclasses can override this policy to // perform SVC_HANDLER creation in any way that they like (such as // creating subclass instances of SVC_HANDLER, using a singleton, // dynamically linking the handler, etc.). Returns -1 if failure, // else 0. virtual int connect_svc_handler (SVC_HANDLER *&svc_handler, const ACE_PEER_CONNECTOR_ADDR &remote_addr, ACE_Time_Value *timeout, const ACE_PEER_CONNECTOR_ADDR &local_addr, int reuse_addr, int flags, int perms); virtual int connect_svc_handler (SVC_HANDLER *&svc_handler, SVC_HANDLER *&sh_copy, const ACE_PEER_CONNECTOR_ADDR &remote_addr, ACE_Time_Value *timeout, const ACE_PEER_CONNECTOR_ADDR &local_addr, int reuse_addr, int flags, int perms); // Bridge method for connecting the to the // . The default behavior delegates to the // . virtual int activate_svc_handler (SVC_HANDLER *svc_handler); // Bridge method for activating a with the appropriate // concurrency strategy. The default behavior of this method is to // activate the SVC_HANDLER by calling its open() method (which // allows the SVC_HANDLER to define its own concurrency strategy). // However, subclasses can override this strategy to do more // sophisticated concurrency activations (such as creating the // SVC_HANDLER as an "active object" via multi-threading or // multi-processing). virtual int handle_input (ACE_HANDLE); // Called by ACE_Reactor when asynchronous connections fail. virtual int handle_output (ACE_HANDLE); // Called by ACE_Reactor when asynchronous connections succeed. virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE); // Called by ACE_Reactor when asynchronous connections complete (on // some platforms only). // = Dynamic linking hooks. virtual int init (int argc, ASYS_TCHAR *argv[]); // Default version does no work and returns -1. Must be overloaded // by application developer to do anything meaningful. virtual int fini (void); // Calls to shutdown the Connector gracefully. virtual int info (ASYS_TCHAR **, size_t) const; // Default version returns address info in . // = Demultiplexing hooks. virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); // Terminate the Client ACE_Connector by iterating over any // unconnected ACE_Svc_Handler's and removing them from the // ACE_Reactor. virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg); // This method is called if a connection times out before // completing. // = Service management hooks. virtual int suspend (void); // Default version does no work and returns -1. Must be overloaded // by application developer to do anything meaningful. virtual int resume (void); // Default version does no work and returns -1. Must be overloaded // by application developer to do anything meaningful. int create_AST (SVC_HANDLER *, const ACE_Synch_Options &); // Creates and inserts an ACE_Svc_Tuple into the . // so that we can continue accepting this connection asynchronously. int cleanup_AST (ACE_HANDLE, AST *&); // Cleanup the and returns the appropriate // ACE_Svc_Tuple (which is 0 if there is no associated tuple). virtual int connect_i (SVC_HANDLER *&svc_handler, SVC_HANDLER **sh_copy, const ACE_PEER_CONNECTOR_ADDR &remote_addr, const ACE_Synch_Options &synch_options, const ACE_PEER_CONNECTOR_ADDR &local_addr, int reuse_addr, int flags, int perms); // Implementation the connect() methods MAP_MANAGER handler_map_; // Lookup table that maps an I/O handle to a SVC_HANDLER *. private: ACE_PEER_CONNECTOR connector_; // This is the concrete connector factory (it keeps no state so the // is reentrant). char closing_; // Keeps track of whether we are in the process of closing (required // to avoid circular calls to ). int flags_; // Flags that indicate how 's should be initialized // prior to being activated. Right now, the only flag that is // processed is , which enabled non-blocking I/O on // the when it is opened. }; template class ACE_Strategy_Connector : public ACE_Connector { // = TITLE // Abstract factory for creating a service handler // (SVC_HANDLER), connecting the SVC_HANDLER, and activating the // SVC_HANDLER. // // = DESCRIPTION // Implements a flexible and extensible set of strategies for // actively establishing connections with clients. There are // three main strategies: (1) creating a SVC_HANDLER, (2) // actively connecting a new connection from a client into the // SVC_HANDLER, and (3) activating the SVC_HANDLER with a // particular concurrency mechanism. public: ACE_Strategy_Connector (ACE_Reactor *r = ACE_Reactor::instance (), ACE_Creation_Strategy * = 0, ACE_Connect_Strategy * = 0, ACE_Concurrency_Strategy * = 0, int flags = 0); // Initialize a connector. indicates how 's // should be initialized prior to being activated. Right now, the // only flag that is processed is , which enabled // non-blocking I/O on the when it is opened. virtual int open (ACE_Reactor *r, int flags); // Initialize a connector. indicates how 's // should be initialized prior to being activated. Right now, the // only flag that is processed is , which enabled // non-blocking I/O on the when it is opened. // Default strategies would be created and used. virtual int open (ACE_Reactor *r = ACE_Reactor::instance (), ACE_Creation_Strategy * = 0, ACE_Connect_Strategy * = 0, ACE_Concurrency_Strategy * = 0, int flags = 0); // Initialize a connector. indicates how 's // should be initialized prior to being activated. Right now, the // only flag that is processed is , which enabled // non-blocking I/O on the when it is opened. virtual ~ACE_Strategy_Connector (void); // Shutdown a connector and release resources. virtual int close (void); // Close down the Connector // = Define some useful typedefs traits. typedef ACE_Creation_Strategy CREATION_STRATEGY; typedef ACE_Connect_Strategy CONNECT_STRATEGY; typedef ACE_Concurrency_Strategy CONCURRENCY_STRATEGY; typedef ACE_Connector SUPER; // = Strategies accessors virtual ACE_Creation_Strategy *creation_strategy (void) const; virtual ACE_Connect_Strategy *connect_strategy (void) const; virtual ACE_Concurrency_Strategy *concurrency_strategy (void) const; protected: // = The following three methods define the 's strategies // for creating, connecting, and activating 's, // respectively. virtual int make_svc_handler (SVC_HANDLER *&sh); // Bridge method for creating a . The strategy for // creating a are configured into the Connector via // it's . The default is to create a new // only if == 0, else is unchanged. // However, subclasses can override this policy to perform // creation in any way that they like (such as // creating subclass instances of , using a singleton, // dynamically linking the handler, etc.). Returns -1 if failure, // else 0. virtual int connect_svc_handler (SVC_HANDLER *&sh, const ACE_PEER_CONNECTOR_ADDR &remote_addr, ACE_Time_Value *timeout, const ACE_PEER_CONNECTOR_ADDR &local_addr, int reuse_addr, int flags, int perms); // Bridge method for connecting the new connection into the // . The default behavior delegates to the // in the . virtual int connect_svc_handler (SVC_HANDLER *&sh, SVC_HANDLER *&sh_copy, const ACE_PEER_CONNECTOR_ADDR &remote_addr, ACE_Time_Value *timeout, const ACE_PEER_CONNECTOR_ADDR &local_addr, int reuse_addr, int flags, int perms); // Bridge method for connecting the new connection into the // . The default behavior delegates to the // in the . // is used to obtain a copy of the pointer, but that // can be kept in the stack; the motivation is a bit too long to // include here, but basically we want to modify safely, using // the internal locks in the Connect_Strategy, while saving a TSS // copy in , usually located in the stack. virtual int activate_svc_handler (SVC_HANDLER *svc_handler); // Bridge method for activating a with the appropriate // concurrency strategy. The default behavior of this method is to // activate the by calling its method (which // allows the to define its own concurrency strategy). // However, subclasses can override this strategy to do more // sophisticated concurrency activations (such as creating the // as an "active object" via multi-threading or // multi-processing). // = Strategy objects. CREATION_STRATEGY *creation_strategy_; // Creation strategy for an . int delete_creation_strategy_; // 1 if created the creation strategy and thus should // delete it, else 0. CONNECT_STRATEGY *connect_strategy_; // Connect strategy for a . int delete_connect_strategy_; // 1 if created the connect strategy and thus should // delete it, else 0. CONCURRENCY_STRATEGY *concurrency_strategy_; // Concurrency strategy for an . int delete_concurrency_strategy_; // 1 if created the concurrency strategy and thus should // delete it, else 0. }; #include "ace/Connector.i" #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) #include "ace/Connector.cpp" #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation ("Connector.cpp") #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ #endif /* ACE_CONNECTOR_H */