server/dep/ACE_wrappers/ace/Connector.h

572 lines
21 KiB
C++

// -*- C++ -*-
//=============================================================================
/**
* @file Connector.h
*
* $Id: Connector.h 91527 2010-08-27 15:03:31Z shuston $
*
* @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
*/
//=============================================================================
#ifndef ACE_CONNECTOR_H
#define ACE_CONNECTOR_H
#include /**/ "ace/pre.h"
#include "ace/Service_Object.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "ace/Strategies_T.h"
#include "ace/Synch_Options.h"
#include "ace/Unbounded_Set.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
/**
* @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 SVC_HANDLER>
class ACE_Connector_Base
{
public:
virtual ~ACE_Connector_Base (void) {}
/// 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_Unbounded_Set<ACE_HANDLE> &non_blocking_handles (void) = 0;
};
/**
* @class ACE_NonBlocking_Connect_Handler
*
* @brief Performs non-blocking connects on behalf of the Connector.
*/
template <class SVC_HANDLER>
class ACE_NonBlocking_Connect_Handler : public ACE_Event_Handler
{
public:
/// Constructor.
ACE_NonBlocking_Connect_Handler (ACE_Connector_Base<SVC_HANDLER> &connector,
SVC_HANDLER *,
long timer_id);
/// Destructor.
~ACE_NonBlocking_Connect_Handler (void);
/// Close up and return underlying SVC_HANDLER through @c sh.
/**
* If the return value is true the close was performed succesfully,
* implying that this object was removed from the reactor and thereby
* (by means of reference counting decremented to 0) deleted.
* If the return value is false, the close was not successful.
* The @c sh does not have any connection to the return
* value. The argument will return a valid svc_handler object if a
* valid one exists within the object. Returning a valid svc_handler
* pointer also invalidates the svc_handler contained in this
* object.
*/
bool close (SVC_HANDLER *&sh);
/// Get SVC_HANDLER.
SVC_HANDLER *svc_handler (void);
/// Get handle.
ACE_HANDLE handle (void);
/// Set handle.
void handle (ACE_HANDLE);
/// 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_Dev_Poll_Reactor when asynchronous connections fail.
virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
/// 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<SVC_HANDLER> &connector_;
/// Associated SVC_HANDLER.
SVC_HANDLER *svc_handler_;
/// Same as svc_handler_ if svc_handler_ is reference counted.
SVC_HANDLER *cleanup_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 SVC_HANDLER, ACE_PEER_CONNECTOR_1>
class ACE_Connector : public ACE_Connector_Base<SVC_HANDLER>, public ACE_Service_Object
{
public:
// Useful STL-style traits.
typedef typename SVC_HANDLER::addr_type addr_type;
typedef ACE_PEER_CONNECTOR connector_type;
typedef SVC_HANDLER handler_type;
typedef typename SVC_HANDLER::stream_type stream_type;
typedef typename ACE_PEER_CONNECTOR::PEER_ADDR peer_addr_type;
typedef ACE_PEER_CONNECTOR_ADDR ACE_PEER_ADDR_TYPEDEF;
/**
* Initialize a connector. @a flags indicates how SVC_HANDLER's
* should be initialized prior to being activated. Right now, the
* only flag that is processed is ACE_NONBLOCK, which enabled
* non-blocking I/O on the SVC_HANDLER when it is opened.
*/
ACE_Connector (ACE_Reactor *r = ACE_Reactor::instance (),
int flags = 0);
/**
* Initialize a connector. @a flags indicates how SVC_HANDLER's
* should be initialized prior to being activated. Right now, the
* only flag that is processed is ACE_NONBLOCK, which enabled
* non-blocking I/O on the SVC_HANDLER 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 @a svc_handler to peer at @a remote_addr
* using @a synch_options. If the caller wants to designate the
* selected @a local_addr they can (and can also insist that the
* @a local_addr be reused by passing a value @a reuse_addr ==
* 1). @a flags and @a perms 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 <close> hook on the @a svc_handler 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
= (peer_addr_type &) ACE_PEER_CONNECTOR_ADDR_ANY,
int reuse_addr = 0,
int flags = O_RDWR,
int perms = 0);
/**
* This is a variation on the previous <connect> method. On cached
* connectors the @a svc_handler_hint 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 @a svc_handler. If the connection fails the
* <close> hook on the @a svc_handler 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
= (peer_addr_type &) ACE_PEER_CONNECTOR_ADDR_ANY,
int reuse_addr = 0,
int flags = O_RDWR,
int perms = 0);
/**
* Initiate connection of @a n @a svc_handlers to peers at
* @a remote_addrs using @a synch_options. Returns -1 if failure
* occurs and 0 otherwise. If @a failed_svc_handlers is non-NULL, a
* 1 is placed in the corresponding index of @a failed_svc_handlers
* for each <svc_handlers[i]> 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 the @a svc_handler that was started asynchronously. Note that
* this is the only case when the Connector does not actively close
* the @a svc_handler. It is left up to the caller of <cancel> to
* decide the fate of the @a svc_handler.
*/
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<SVC_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 @a sh == 0, else @a sh 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 @a svc_handler to the
* @a remote_addr. The default behavior delegates to the
* <PEER_CONNECTOR::connect>.
*/
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 @a svc_handler 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 activate_svc_handler (SVC_HANDLER *svc_handler);
/// Creates and registers ACE_NonBlocking_Connect_Handler.
int nonblocking_connect (SVC_HANDLER *,
const ACE_Synch_Options &);
/// Implementation of the connect 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_Unbounded_Set<ACE_HANDLE> &non_blocking_handles (void);
// = 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[]);
/// Calls handle_close() to shutdown the Connector gracefully.
virtual int fini (void);
/// Default version returns address info in @a buf.
virtual int info (ACE_TCHAR **strp, size_t length) const;
// = Service management hooks.
/// Default version does no work and returns -1. Must be overloaded
/// by application developer to do anything meaningful.
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);
private:
/// This is the peer connector factory.
ACE_PEER_CONNECTOR connector_;
/**
* Flags that indicate how SVC_HANDLER's should be initialized
* prior to being activated. Right now, the only flag that is
* processed is ACE_NONBLOCK, which enabled non-blocking I/O on
* the SVC_HANDLER when it is opened.
*/
int flags_;
/// Pointer to the Reactor.
ACE_Reactor *reactor_;
/// Handle set representing the non-blocking connects in progress.
ACE_Unbounded_Set<ACE_HANDLE> 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 SVC_HANDLER, ACE_PEER_CONNECTOR_1>
class ACE_Strategy_Connector
: public ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2>
{
public:
// Useful STL-style traits.
typedef ACE_Creation_Strategy<SVC_HANDLER>
creation_strategy_type;
typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
connect_strategy_type;
typedef ACE_Concurrency_Strategy<SVC_HANDLER>
concurrency_strategy_type;
typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2>
base_type;
// = Define some useful (old style) traits.
typedef ACE_Creation_Strategy<SVC_HANDLER>
CREATION_STRATEGY;
typedef ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
CONNECT_STRATEGY;
typedef ACE_Concurrency_Strategy<SVC_HANDLER>
CONCURRENCY_STRATEGY;
typedef ACE_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2>
SUPER;
/**
* Initialize a connector. @a flags indicates how SVC_HANDLER's
* should be initialized prior to being activated. Right now, the
* only flag that is processed is ACE_NONBLOCK, which enabled
* non-blocking I/O on the SVC_HANDLER when it is opened.
*/
ACE_Strategy_Connector (ACE_Reactor *r = ACE_Reactor::instance (),
ACE_Creation_Strategy<SVC_HANDLER> * = 0,
ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> * = 0,
ACE_Concurrency_Strategy<SVC_HANDLER> * = 0,
int flags = 0);
/**
* Initialize a connector. @a flags indicates how SVC_HANDLER's
* should be initialized prior to being activated. Right now, the
* only flag that is processed is ACE_NONBLOCK, which enabled
* non-blocking I/O on the SVC_HANDLER when it is opened.
* Default strategies would be created and used.
*/
virtual int open (ACE_Reactor *r,
int flags);
/**
* Initialize a connector. @a flags indicates how SVC_HANDLER's
* should be initialized prior to being activated. Right now, the
* only flag that is processed is ACE_NONBLOCK, which enabled
* non-blocking I/O on the SVC_HANDLER when it is opened.
*/
virtual int open (ACE_Reactor *r = ACE_Reactor::instance (),
ACE_Creation_Strategy<SVC_HANDLER> * = 0,
ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> * = 0,
ACE_Concurrency_Strategy<SVC_HANDLER> * = 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<SVC_HANDLER> *creation_strategy (void) const;
virtual ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *connect_strategy (void) const;
virtual ACE_Concurrency_Strategy<SVC_HANDLER> *concurrency_strategy (void) const;
protected:
// = The following three methods define the <Connector>'s strategies
// for creating, connecting, and activating SVC_HANDLER's,
// respectively.
/**
* Bridge method for creating a SVC_HANDLER. The strategy for
* creating a SVC_HANDLER are configured into the Connector via
* it's <creation_strategy_>. The default is to create a new
* SVC_HANDLER only if @a sh == 0, else @a sh 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 new connection into the
* SVC_HANDLER. The default behavior delegates to the
* <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
*/
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
* SVC_HANDLER. The default behavior delegates to the
* <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
* @a sh_copy is used to obtain a copy of the @a sh 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 @a sh safely, using
* the internal locks in the Connect_Strategy, while saving a TSS
* copy in @a sh_copy, 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 SVC_HANDLER 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 activate_svc_handler (SVC_HANDLER *svc_handler);
// = Strategy objects.
/// Creation strategy for an Connector.
CREATION_STRATEGY *creation_strategy_;
/// True if Connector created the creation strategy and thus should
/// delete it, else false.
bool delete_creation_strategy_;
/// Connect strategy for a Connector.
CONNECT_STRATEGY *connect_strategy_;
/// True if Connector created the connect strategy and thus should
/// delete it, else false.
bool delete_connect_strategy_;
/// Concurrency strategy for a Connector.
CONCURRENCY_STRATEGY *concurrency_strategy_;
/// True if Connector created the concurrency strategy and thus should
/// delete it, else false.
bool delete_concurrency_strategy_;
};
ACE_END_VERSIONED_NAMESPACE_DECL
#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 */