// -*- C++ -*- //============================================================================= /** * @file Connector.h * * $Id$ * * @author Douglas C. Schmidt */ //============================================================================= #ifndef ACE_CONNECTOR_H #define ACE_CONNECTOR_H #include "ace/pre.h" #include "ace/Event_Handler.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Strategies_T.h" #include "ace/Synch_Options.h" /** * @class ACE_Connector_Base * * @brief This base interface allows ACE_NonBlocking_Connect_Handler * to only care about the SVC_HANDLER template parameter of the * ACE_Connector. Otherwise, ACE_NonBlocking_Connect_Handler would * have to be configured with all the template parameters that * ACE_Connector is configured with. */ template class ACE_Connector_Base { public: /// Initialize the Svc_Handler. virtual void initialize_svc_handler (ACE_HANDLE handle, SVC_HANDLER *svc_handler) = 0; /// Return the handle set representing the non-blocking connects in /// progress. virtual ACE_Handle_Set &non_blocking_handles (void) = 0; }; /** * @class ACE_NonBlocking_Connect_Handler * * @brief Performs non-blocking connects on behalf of the Connector. */ template class ACE_NonBlocking_Connect_Handler : public ACE_Event_Handler { public: // Constructor. ACE_NonBlocking_Connect_Handler (ACE_Connector_Base &connector, SVC_HANDLER *, long timer_id); /// Close up and return underlying SVC_HANDLER *. SVC_HANDLER *close (void); /// Get SVC_HANDLER. SVC_HANDLER *svc_handler (void); // = Get/set handle. /// Get handle. ACE_HANDLE handle (void); /// Set handle. void handle (ACE_HANDLE); // = Set/get timer id. /// Get timer id. long timer_id (void); /// Set timer id. void timer_id (long timer_id); /// Called by ACE_Reactor when asynchronous connections fail. virtual int handle_input (ACE_HANDLE); /// Called by ACE_Reactor when asynchronous connections succeed. virtual int handle_output (ACE_HANDLE); /// Called by ACE_Reactor when asynchronous connections suceeds (on /// some platforms only). virtual int handle_exception (ACE_HANDLE fd); /// This method is called if a connection times out before /// completing. virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg); /// Should Reactor resume us if we have been suspended before the /// upcall? virtual int resume_handler (void); /// Dump the state of an object. void dump (void) const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; private: /// Connector base. ACE_Connector_Base &connector_; /// Associated SVC_HANDLER. SVC_HANDLER *svc_handler_; /// Associated timer id. long timer_id_; }; /** * @class ACE_Connector * * @brief Generic factory for actively connecting clients and creating * service handlers (SVC_HANDLERs). * * 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 * actively establishes connections. The SVC_HANDLER is instantiated * with a concrete type that performs the application-specific * service. Both blocking and non-blocking connects are supported. * Further, non-blocking connects support timeouts. */ template class ACE_Connector : public ACE_Connector_Base { public: // Useful STL-style traits. typedef ACE_TYPENAME SVC_HANDLER::addr_type addr_type; typedef ACE_PEER_CONNECTOR connector_type; typedef SVC_HANDLER handler_type; typedef ACE_TYPENAME SVC_HANDLER::stream_type stream_type; // 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 */ typedef ACE_TYPENAME _ACE_PEER_CONNECTOR::PEER_ADDR ACE_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR; /** * Initialize a connector. @a flags 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. */ ACE_Connector (ACE_Reactor *r = ACE_Reactor::instance (), int flags = 0); /** * Initialize a connector. @a flags 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); /// Shutdown a connector and release resources. virtual ~ACE_Connector (void); // = Connection establishment methods. /** * 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, 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_TYPENAME_ACE_PEER_CONNECTOR_PEER_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 (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_TYPENAME_ACE_PEER_CONNECTOR_PEER_ADDR &) ACE_PEER_CONNECTOR_ADDR_ANY, int reuse_addr = 0, int flags = O_RDWR, int perms = 0); /** * 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 connect_n (size_t n, SVC_HANDLER *svc_handlers[], ACE_PEER_CONNECTOR_ADDR remote_addrs[], ACE_TCHAR *failed_svc_handlers = 0, const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults); /** * 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 cancel (SVC_HANDLER *svc_handler); /// Close down the Connector. All pending non-blocking connects are /// canceled and the corresponding svc_handler is closed. virtual int close (void); /// Return the underlying PEER_CONNECTOR object. virtual ACE_PEER_CONNECTOR &connector (void) const; /// Initialize Svc_Handler. virtual void initialize_svc_handler (ACE_HANDLE handle, SVC_HANDLER *svc_handler); /// Set Reactor. virtual void reactor (ACE_Reactor *reactor); /// Get Reactor. virtual ACE_Reactor *reactor (void) const; /// Dump the state of an object. void dump (void) const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: // = Helpful typedefs. typedef ACE_NonBlocking_Connect_Handler NBCH; // = The following two methods define the Connector's strategies for // creating, connecting, and activating SVC_HANDLER's, respectively. /** * 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 make_svc_handler (SVC_HANDLER *&sh); /** * Bridge method for connecting the to the * . The default behavior delegates to the * . */ 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 activating a with the appropriate * concurrency strategy. The default behavior of this method is to * activate the SVC_HANDLER by calling its 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 activate_svc_handler (SVC_HANDLER *svc_handler); /// Creates and registers ACE_NonBlocking_Connect_Handler. int nonblocking_connect (SVC_HANDLER *, const ACE_Synch_Options &); /// Implementation the methods. 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); /// Return the handle set representing the non-blocking connects in /// progress. ACE_Handle_Set &non_blocking_handles (void); private: /// This is the peer connector factory. ACE_PEER_CONNECTOR connector_; /** * 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. */ int flags_; /// Pointer to the Reactor. ACE_Reactor *reactor_; /// Handle set representing the non-blocking connects in progress. ACE_Handle_Set non_blocking_handles_; }; /** * @class ACE_Strategy_Connector * * @brief Abstract factory for creating a service handler * (SVC_HANDLER), connecting the SVC_HANDLER, and activating the * SVC_HANDLER. * * 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 initiating a new connection from the client, * and (3) activating the SVC_HANDLER with a * particular concurrency mechanism after the connection is established. */ template class ACE_Strategy_Connector : public ACE_Connector { public: // Useful STL-style traits. typedef ACE_Creation_Strategy creation_strategy_type; typedef ACE_Connect_Strategy connect_strategy_type; typedef ACE_Concurrency_Strategy concurrency_strategy_type; typedef ACE_Connector base_type; // = Define some useful (old style) traits. typedef ACE_Creation_Strategy CREATION_STRATEGY; typedef ACE_Connect_Strategy CONNECT_STRATEGY; typedef ACE_Concurrency_Strategy CONCURRENCY_STRATEGY; typedef ACE_Connector SUPER; /** * 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. */ 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. * Default strategies would be created and used. */ 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. */ virtual int open (ACE_Reactor *r = ACE_Reactor::instance (), ACE_Creation_Strategy * = 0, ACE_Connect_Strategy * = 0, ACE_Concurrency_Strategy * = 0, int flags = 0); /// Shutdown a connector and release resources. virtual ~ACE_Strategy_Connector (void); /// Close down the Connector virtual int close (void); // = 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. /** * 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 make_svc_handler (SVC_HANDLER *&sh); /** * 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, 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 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 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). */ virtual int activate_svc_handler (SVC_HANDLER *svc_handler); // = Strategy objects. /// Creation strategy for an . CREATION_STRATEGY *creation_strategy_; /// 1 if created the creation strategy and thus should /// delete it, else 0. int delete_creation_strategy_; /// Connect strategy for a . CONNECT_STRATEGY *connect_strategy_; /// 1 if created the connect strategy and thus should /// delete it, else 0. int delete_connect_strategy_; /// Concurrency strategy for an . CONCURRENCY_STRATEGY *concurrency_strategy_; /// 1 if created the concurrency strategy and thus should /// delete it, else 0. int delete_concurrency_strategy_; }; #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 */ #include "ace/post.h" #endif /* ACE_CONNECTOR_H */