3 //=============================================================================
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
9 //=============================================================================
11 #ifndef ACE_CONNECTOR_H
12 #define ACE_CONNECTOR_H
14 #include /**/ "ace/pre.h"
16 #include "ace/Service_Object.h"
18 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 #endif /* ACE_LACKS_PRAGMA_ONCE */
22 #include "ace/Strategies_T.h"
23 #include "ace/Synch_Options.h"
24 #include "ace/Unbounded_Set.h"
26 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
29 * @class ACE_Connector_Base
31 * @brief This base interface allows ACE_NonBlocking_Connect_Handler
32 * to only care about the SVC_HANDLER template parameter of the
33 * ACE_Connector. Otherwise, ACE_NonBlocking_Connect_Handler would
34 * have to be configured with all the template parameters that
35 * ACE_Connector is configured with.
37 template <class SVC_HANDLER
>
38 class ACE_Connector_Base
41 virtual ~ACE_Connector_Base () = default;
43 /// Initialize the Svc_Handler.
44 virtual void initialize_svc_handler (ACE_HANDLE handle
,
45 SVC_HANDLER
*svc_handler
) = 0;
47 /// Return the handle set representing the non-blocking connects in
49 virtual ACE_Unbounded_Set
<ACE_HANDLE
> &non_blocking_handles () = 0;
53 * @class ACE_NonBlocking_Connect_Handler
55 * @brief Performs non-blocking connects on behalf of the Connector.
57 template <class SVC_HANDLER
>
58 class ACE_NonBlocking_Connect_Handler
: public ACE_Event_Handler
62 ACE_NonBlocking_Connect_Handler (ACE_Connector_Base
<SVC_HANDLER
> &connector
,
67 ~ACE_NonBlocking_Connect_Handler ();
69 /// Close up and return underlying SVC_HANDLER through @c sh.
71 * If the return value is true the close was performed successfully,
72 * implying that this object was removed from the reactor and thereby
73 * (by means of reference counting decremented to 0) deleted.
74 * If the return value is false, the close was not successful.
75 * The @c sh does not have any connection to the return
76 * value. The argument will return a valid svc_handler object if a
77 * valid one exists within the object. Returning a valid svc_handler
78 * pointer also invalidates the svc_handler contained in this
81 bool close (SVC_HANDLER
*&sh
);
84 SVC_HANDLER
*svc_handler ();
90 void handle (ACE_HANDLE
);
96 void timer_id (long timer_id
);
98 /// Called by ACE_Reactor when asynchronous connections fail.
99 virtual int handle_input (ACE_HANDLE
);
101 /// Called by ACE_Dev_Poll_Reactor when asynchronous connections fail.
102 virtual int handle_close (ACE_HANDLE
, ACE_Reactor_Mask
);
104 /// Called by ACE_Reactor when asynchronous connections succeed.
105 virtual int handle_output (ACE_HANDLE
);
107 /// Called by ACE_Reactor when asynchronous connections suceeds (on
108 /// some platforms only).
109 virtual int handle_exception (ACE_HANDLE fd
);
111 /// This method is called if a connection times out before
113 virtual int handle_timeout (const ACE_Time_Value
&tv
, const void *arg
);
115 /// Should Reactor resume us if we have been suspended before the upcall?
116 virtual int resume_handler ();
118 /// Dump the state of an object.
121 /// Declare the dynamic allocation hooks.
122 ACE_ALLOC_HOOK_DECLARE
;
126 ACE_Connector_Base
<SVC_HANDLER
> &connector_
;
128 /// Associated SVC_HANDLER.
129 SVC_HANDLER
*svc_handler_
;
131 /// Same as svc_handler_ if svc_handler_ is reference counted.
132 SVC_HANDLER
*cleanup_svc_handler_
;
134 /// Associated timer id.
139 * @class ACE_Connector
141 * @brief Generic factory for actively connecting clients and creating
142 * service handlers (SVC_HANDLERs).
144 * Implements the strategy for actively establishing connections with
145 * clients. Both blocking and non-blocking connects are supported.
146 * Moreover, non-blocking connects support timeouts.
148 * An ACE_Connector is parameterized by concrete types that conform to
149 * the interfaces of SVC_HANDLER and PEER_CONNECTOR described below.
151 * @tparam SVC_HANDLER The name of the concrete type that performs the
152 * application-specific service. The SVC_HANDLER typically
153 * inherits from ACE_Svc_Handler. @see Svc_Handler.h.
155 * @tparam PEER_CONNECTOR The name of the class that implements the
156 * PEER_CONNECTOR endpoint (e.g., ACE_SOCK_Connector) to
157 * passively establish connections. A PEER_CONNECTOR
158 * implementation must provide a PEER_STREAM and PEER_ADDR
159 * trait to identify the type of stream (e.g.,
160 * ACE_SOCK_Stream) and type of address (e.g., ACE_INET_Addr)
161 * used by the endpoint.
163 template <typename SVC_HANDLER
, typename PEER_CONNECTOR
>
164 class ACE_Connector
: public ACE_Connector_Base
<SVC_HANDLER
>, public ACE_Service_Object
167 // Useful STL-style traits.
168 typedef typename
SVC_HANDLER::addr_type addr_type
;
169 typedef PEER_CONNECTOR connector_type
;
170 typedef SVC_HANDLER handler_type
;
171 typedef typename
SVC_HANDLER::stream_type stream_type
;
172 typedef typename
PEER_CONNECTOR::PEER_ADDR peer_addr_type
;
173 typedef typename
PEER_CONNECTOR::PEER_ADDR PEER_ADDR_TYPEDEF
;
176 * Initialize a connector. @a flags indicates how SVC_HANDLER's
177 * should be initialized prior to being activated. Right now, the
178 * only flag that is processed is ACE_NONBLOCK, which enabled
179 * non-blocking I/O on the SVC_HANDLER when it is opened.
181 ACE_Connector (ACE_Reactor
*r
= ACE_Reactor::instance (),
185 * Initialize a connector. @a flags indicates how SVC_HANDLER's
186 * should be initialized prior to being activated. Right now, the
187 * only flag that is processed is ACE_NONBLOCK, which enabled
188 * non-blocking I/O on the SVC_HANDLER when it is opened.
190 virtual int open (ACE_Reactor
*r
= ACE_Reactor::instance (),
193 /// Shutdown a connector and release resources.
194 virtual ~ACE_Connector ();
196 // = Connection establishment methods.
199 * Initiate connection of @a svc_handler to peer at @a remote_addr
200 * using @a synch_options. If the caller wants to designate the
201 * selected @a local_addr they can (and can also insist that the
202 * @a local_addr be reused by passing a value @a reuse_addr ==
203 * 1). @a flags and @a perms can be used to pass any flags that are
204 * needed to perform specific operations such as opening a file
205 * within connect with certain permissions. If the connection fails
206 * the <close> hook on the @a svc_handler will be called
207 * automatically to prevent resource leaks.
209 virtual int connect (SVC_HANDLER
*&svc_handler
,
210 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
211 const ACE_Synch_Options
&synch_options
= ACE_Synch_Options::defaults
,
212 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
213 = reinterpret_cast<const peer_addr_type
&>(peer_addr_type::sap_any
),
219 * This is a variation on the previous <connect> method. On cached
220 * connectors the @a svc_handler_hint variable can be used as a hint
221 * for future lookups. Since this variable is modified in the
222 * context of the internal cache its use is thread-safe. But the
223 * actual svc_handler for the current connection is returned in the
224 * second parameter @a svc_handler. If the connection fails the
225 * <close> hook on the @a svc_handler will be called automatically to
226 * prevent resource leaks.
228 virtual int connect (SVC_HANDLER
*&svc_handler_hint
,
229 SVC_HANDLER
*&svc_handler
,
230 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
231 const ACE_Synch_Options
&synch_options
= ACE_Synch_Options::defaults
,
232 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
233 = reinterpret_cast<const peer_addr_type
&>(peer_addr_type::sap_any
),
239 * Initiate connection of @a n @a svc_handlers to peers at
240 * @a remote_addrs using @a synch_options. Returns -1 if failure
241 * occurs and 0 otherwise. If @a failed_svc_handlers is non-NULL, a
242 * 1 is placed in the corresponding index of @a failed_svc_handlers
243 * for each <svc_handlers[i]> that failed to connect, else a 0 is
244 * placed in that index.
246 virtual int connect_n (size_t n
,
247 SVC_HANDLER
*svc_handlers
[],
248 typename
PEER_CONNECTOR::PEER_ADDR remote_addrs
[],
249 ACE_TCHAR
*failed_svc_handlers
= 0,
250 const ACE_Synch_Options
&synch_options
=
251 ACE_Synch_Options::defaults
);
254 * Cancel the @a svc_handler that was started asynchronously. Note that
255 * this is the only case when the Connector does not actively close
256 * the @a svc_handler. It is left up to the caller of <cancel> to
257 * decide the fate of the @a svc_handler.
259 virtual int cancel (SVC_HANDLER
*svc_handler
);
261 /// Close down the Connector. All pending non-blocking connects are
262 /// canceled and the corresponding svc_handler is closed.
263 virtual int close ();
265 /// Return the underlying PEER_CONNECTOR object.
266 virtual PEER_CONNECTOR
&connector () const;
268 /// Initialize Svc_Handler.
269 virtual void initialize_svc_handler (ACE_HANDLE handle
,
270 SVC_HANDLER
*svc_handler
);
273 virtual void reactor (ACE_Reactor
*reactor
);
276 virtual ACE_Reactor
*reactor () const;
278 /// Dump the state of an object.
281 /// Declare the dynamic allocation hooks.
282 ACE_ALLOC_HOOK_DECLARE
;
285 // = Helpful typedefs.
286 typedef ACE_NonBlocking_Connect_Handler
<SVC_HANDLER
> NBCH
;
288 // = The following two methods define the Connector's strategies for
289 // creating, connecting, and activating SVC_HANDLER's, respectively.
292 * Bridge method for creating a SVC_HANDLER. The default is to
293 * create a new SVC_HANDLER only if @a sh == 0, else @a sh is
294 * unchanged. However, subclasses can override this policy to
295 * perform SVC_HANDLER creation in any way that they like (such as
296 * creating subclass instances of SVC_HANDLER, using a singleton,
297 * dynamically linking the handler, etc.). Returns -1 if failure,
300 virtual int make_svc_handler (SVC_HANDLER
*&sh
);
303 * Bridge method for connecting the @a svc_handler to the
304 * @a remote_addr. The default behavior delegates to the
305 * <PEER_CONNECTOR::connect>.
307 virtual int connect_svc_handler (SVC_HANDLER
*&svc_handler
,
308 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
309 ACE_Time_Value
*timeout
,
310 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
,
314 virtual int connect_svc_handler (SVC_HANDLER
*&svc_handler
,
315 SVC_HANDLER
*&sh_copy
,
316 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
317 ACE_Time_Value
*timeout
,
318 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
,
324 * Bridge method for activating a @a svc_handler with the appropriate
325 * concurrency strategy. The default behavior of this method is to
326 * activate the SVC_HANDLER by calling its <open> method (which
327 * allows the SVC_HANDLER to define its own concurrency strategy).
328 * However, subclasses can override this strategy to do more
329 * sophisticated concurrency activations (such as creating the
330 * SVC_HANDLER as an "active object" via multi-threading or
333 virtual int activate_svc_handler (SVC_HANDLER
*svc_handler
);
335 /// Creates and registers ACE_NonBlocking_Connect_Handler.
336 int nonblocking_connect (SVC_HANDLER
*,
337 const ACE_Synch_Options
&);
339 /// Implementation of the connect methods.
340 virtual int connect_i (SVC_HANDLER
*&svc_handler
,
341 SVC_HANDLER
**sh_copy
,
342 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
343 const ACE_Synch_Options
&synch_options
,
344 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
,
349 /// Return the handle set representing the non-blocking connects in
351 ACE_Unbounded_Set
<ACE_HANDLE
> &non_blocking_handles ();
353 // = Dynamic linking hooks.
354 /// Default version does no work and returns -1. Must be overloaded
355 /// by application developer to do anything meaningful.
356 virtual int init (int argc
, ACE_TCHAR
*argv
[]);
358 /// Calls handle_close() to shutdown the Connector gracefully.
361 /// Default version returns address info in @a buf.
362 virtual int info (ACE_TCHAR
**strp
, size_t length
) const;
364 // = Service management hooks.
365 /// Default version does no work and returns -1. Must be overloaded
366 /// by application developer to do anything meaningful.
367 virtual int suspend ();
369 /// Default version does no work and returns -1. Must be overloaded
370 /// by application developer to do anything meaningful.
371 virtual int resume ();
374 /// This is the peer connector factory.
375 PEER_CONNECTOR connector_
;
378 * Flags that indicate how SVC_HANDLER's should be initialized
379 * prior to being activated. Right now, the only flag that is
380 * processed is ACE_NONBLOCK, which enabled non-blocking I/O on
381 * the SVC_HANDLER when it is opened.
385 /// Pointer to the Reactor.
386 ACE_Reactor
*reactor_
;
388 /// Handle set representing the non-blocking connects in progress.
389 ACE_Unbounded_Set
<ACE_HANDLE
> non_blocking_handles_
;
393 * @class ACE_Strategy_Connector
395 * @brief Abstract factory for creating a service handler
396 * (SVC_HANDLER), connecting the SVC_HANDLER, and activating the
399 * Implements a flexible and extensible set of strategies for
400 * actively establishing connections with clients. There are
401 * three main strategies: (1) creating a SVC_HANDLER, (2)
402 * actively initiating a new connection from the client,
403 * and (3) activating the SVC_HANDLER with a
404 * particular concurrency mechanism after the connection is established.
406 template <class SVC_HANDLER
, typename PEER_CONNECTOR
>
407 class ACE_Strategy_Connector
408 : public ACE_Connector
<SVC_HANDLER
, PEER_CONNECTOR
>
411 // Useful STL-style traits.
412 typedef ACE_Creation_Strategy
<SVC_HANDLER
>
413 creation_strategy_type
;
414 typedef ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
>
415 connect_strategy_type
;
416 typedef ACE_Concurrency_Strategy
<SVC_HANDLER
>
417 concurrency_strategy_type
;
418 typedef ACE_Connector
<SVC_HANDLER
, PEER_CONNECTOR
>
421 // = Define some useful (old style) traits.
422 typedef ACE_Creation_Strategy
<SVC_HANDLER
>
424 typedef ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
>
426 typedef ACE_Concurrency_Strategy
<SVC_HANDLER
>
427 CONCURRENCY_STRATEGY
;
428 typedef ACE_Connector
<SVC_HANDLER
, PEER_CONNECTOR
>
432 * Initialize a connector. @a flags indicates how SVC_HANDLER's
433 * should be initialized prior to being activated. Right now, the
434 * only flag that is processed is ACE_NONBLOCK, which enabled
435 * non-blocking I/O on the SVC_HANDLER when it is opened.
437 ACE_Strategy_Connector (ACE_Reactor
*r
= ACE_Reactor::instance (),
438 ACE_Creation_Strategy
<SVC_HANDLER
> * = 0,
439 ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
> * = 0,
440 ACE_Concurrency_Strategy
<SVC_HANDLER
> * = 0,
444 * Initialize a connector. @a flags indicates how SVC_HANDLER's
445 * should be initialized prior to being activated. Right now, the
446 * only flag that is processed is ACE_NONBLOCK, which enabled
447 * non-blocking I/O on the SVC_HANDLER when it is opened.
448 * Default strategies would be created and used.
450 virtual int open (ACE_Reactor
*r
,
454 * Initialize a connector. @a flags indicates how SVC_HANDLER's
455 * should be initialized prior to being activated. Right now, the
456 * only flag that is processed is ACE_NONBLOCK, which enabled
457 * non-blocking I/O on the SVC_HANDLER when it is opened.
459 virtual int open (ACE_Reactor
*r
= ACE_Reactor::instance (),
460 ACE_Creation_Strategy
<SVC_HANDLER
> * = 0,
461 ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
> * = 0,
462 ACE_Concurrency_Strategy
<SVC_HANDLER
> * = 0,
465 /// Shutdown a connector and release resources.
466 virtual ~ACE_Strategy_Connector ();
468 /// Close down the Connector
469 virtual int close ();
471 // = Strategies accessors
472 virtual ACE_Creation_Strategy
<SVC_HANDLER
> *creation_strategy () const;
473 virtual ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
> *connect_strategy () const;
474 virtual ACE_Concurrency_Strategy
<SVC_HANDLER
> *concurrency_strategy () const;
476 /// Declare the dynamic allocation hooks.
477 ACE_ALLOC_HOOK_DECLARE
;
480 // = The following three methods define the <Connector>'s strategies
481 // for creating, connecting, and activating SVC_HANDLER's,
485 * Bridge method for creating a SVC_HANDLER. The strategy for
486 * creating a SVC_HANDLER are configured into the Connector via
487 * it's <creation_strategy_>. The default is to create a new
488 * SVC_HANDLER only if @a sh == 0, else @a sh is unchanged.
489 * However, subclasses can override this policy to perform
490 * SVC_HANDLER creation in any way that they like (such as
491 * creating subclass instances of SVC_HANDLER, using a singleton,
492 * dynamically linking the handler, etc.). Returns -1 if failure,
495 virtual int make_svc_handler (SVC_HANDLER
*&sh
);
498 * Bridge method for connecting the new connection into the
499 * SVC_HANDLER. The default behavior delegates to the
500 * <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
502 virtual int connect_svc_handler (SVC_HANDLER
*&sh
,
503 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
504 ACE_Time_Value
*timeout
,
505 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
,
511 * Bridge method for connecting the new connection into the
512 * SVC_HANDLER. The default behavior delegates to the
513 * <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
514 * @a sh_copy is used to obtain a copy of the @a sh pointer, but that
515 * can be kept in the stack; the motivation is a bit too long to
516 * include here, but basically we want to modify @a sh safely, using
517 * the internal locks in the Connect_Strategy, while saving a TSS
518 * copy in @a sh_copy, usually located in the stack.
520 virtual int connect_svc_handler (SVC_HANDLER
*&sh
,
521 SVC_HANDLER
*&sh_copy
,
522 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
523 ACE_Time_Value
*timeout
,
524 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
,
530 * Bridge method for activating a SVC_HANDLER with the appropriate
531 * concurrency strategy. The default behavior of this method is to
532 * activate the SVC_HANDLER by calling its <open> method (which
533 * allows the SVC_HANDLER to define its own concurrency strategy).
534 * However, subclasses can override this strategy to do more
535 * sophisticated concurrency activations (such as creating the
536 * SVC_HANDLER as an "active object" via multi-threading or
539 virtual int activate_svc_handler (SVC_HANDLER
*svc_handler
);
541 // = Strategy objects.
543 /// Creation strategy for an Connector.
544 CREATION_STRATEGY
*creation_strategy_
;
546 /// True if Connector created the creation strategy and thus should
547 /// delete it, else false.
548 bool delete_creation_strategy_
;
550 /// Connect strategy for a Connector.
551 CONNECT_STRATEGY
*connect_strategy_
;
553 /// True if Connector created the connect strategy and thus should
554 /// delete it, else false.
555 bool delete_connect_strategy_
;
557 /// Concurrency strategy for a Connector.
558 CONCURRENCY_STRATEGY
*concurrency_strategy_
;
560 /// True if Connector created the concurrency strategy and thus should
561 /// delete it, else false.
562 bool delete_concurrency_strategy_
;
565 ACE_END_VERSIONED_NAMESPACE_DECL
567 #include "ace/Connector.cpp"
569 #include /**/ "ace/post.h"
571 #endif /* ACE_CONNECTOR_H */