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 (void) {}
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 (void) = 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 (void);
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 (void);
87 ACE_HANDLE
handle (void);
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 (void);
118 /// Dump the state of an object.
119 void dump (void) const;
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 (void);
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 (void);
265 /// Return the underlying PEER_CONNECTOR object.
266 virtual PEER_CONNECTOR
&connector (void) 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 (void) const;
278 /// Dump the state of an object.
279 void dump (void) const;
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 (void);
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.
359 virtual int fini (void);
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 (void);
369 /// Default version does no work and returns -1. Must be overloaded
370 /// by application developer to do anything meaningful.
371 virtual int resume (void);
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_
;
394 * @class ACE_Strategy_Connector
396 * @brief Abstract factory for creating a service handler
397 * (SVC_HANDLER), connecting the SVC_HANDLER, and activating the
400 * Implements a flexible and extensible set of strategies for
401 * actively establishing connections with clients. There are
402 * three main strategies: (1) creating a SVC_HANDLER, (2)
403 * actively initiating a new connection from the client,
404 * and (3) activating the SVC_HANDLER with a
405 * particular concurrency mechanism after the connection is established.
407 template <class SVC_HANDLER
, typename PEER_CONNECTOR
>
408 class ACE_Strategy_Connector
409 : public ACE_Connector
<SVC_HANDLER
, PEER_CONNECTOR
>
412 // Useful STL-style traits.
413 typedef ACE_Creation_Strategy
<SVC_HANDLER
>
414 creation_strategy_type
;
415 typedef ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
>
416 connect_strategy_type
;
417 typedef ACE_Concurrency_Strategy
<SVC_HANDLER
>
418 concurrency_strategy_type
;
419 typedef ACE_Connector
<SVC_HANDLER
, PEER_CONNECTOR
>
422 // = Define some useful (old style) traits.
423 typedef ACE_Creation_Strategy
<SVC_HANDLER
>
425 typedef ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
>
427 typedef ACE_Concurrency_Strategy
<SVC_HANDLER
>
428 CONCURRENCY_STRATEGY
;
429 typedef ACE_Connector
<SVC_HANDLER
, PEER_CONNECTOR
>
433 * Initialize a connector. @a flags indicates how SVC_HANDLER's
434 * should be initialized prior to being activated. Right now, the
435 * only flag that is processed is ACE_NONBLOCK, which enabled
436 * non-blocking I/O on the SVC_HANDLER when it is opened.
438 ACE_Strategy_Connector (ACE_Reactor
*r
= ACE_Reactor::instance (),
439 ACE_Creation_Strategy
<SVC_HANDLER
> * = 0,
440 ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
> * = 0,
441 ACE_Concurrency_Strategy
<SVC_HANDLER
> * = 0,
445 * Initialize a connector. @a flags indicates how SVC_HANDLER's
446 * should be initialized prior to being activated. Right now, the
447 * only flag that is processed is ACE_NONBLOCK, which enabled
448 * non-blocking I/O on the SVC_HANDLER when it is opened.
449 * Default strategies would be created and used.
451 virtual int open (ACE_Reactor
*r
,
455 * Initialize a connector. @a flags indicates how SVC_HANDLER's
456 * should be initialized prior to being activated. Right now, the
457 * only flag that is processed is ACE_NONBLOCK, which enabled
458 * non-blocking I/O on the SVC_HANDLER when it is opened.
460 virtual int open (ACE_Reactor
*r
= ACE_Reactor::instance (),
461 ACE_Creation_Strategy
<SVC_HANDLER
> * = 0,
462 ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
> * = 0,
463 ACE_Concurrency_Strategy
<SVC_HANDLER
> * = 0,
466 /// Shutdown a connector and release resources.
467 virtual ~ACE_Strategy_Connector (void);
469 /// Close down the Connector
470 virtual int close (void);
472 // = Strategies accessors
473 virtual ACE_Creation_Strategy
<SVC_HANDLER
> *creation_strategy (void) const;
474 virtual ACE_Connect_Strategy
<SVC_HANDLER
, PEER_CONNECTOR
> *connect_strategy (void) const;
475 virtual ACE_Concurrency_Strategy
<SVC_HANDLER
> *concurrency_strategy (void) const;
477 /// Declare the dynamic allocation hooks.
478 ACE_ALLOC_HOOK_DECLARE
;
481 // = The following three methods define the <Connector>'s strategies
482 // for creating, connecting, and activating SVC_HANDLER's,
486 * Bridge method for creating a SVC_HANDLER. The strategy for
487 * creating a SVC_HANDLER are configured into the Connector via
488 * it's <creation_strategy_>. The default is to create a new
489 * SVC_HANDLER only if @a sh == 0, else @a sh is unchanged.
490 * However, subclasses can override this policy to perform
491 * SVC_HANDLER creation in any way that they like (such as
492 * creating subclass instances of SVC_HANDLER, using a singleton,
493 * dynamically linking the handler, etc.). Returns -1 if failure,
496 virtual int make_svc_handler (SVC_HANDLER
*&sh
);
499 * Bridge method for connecting the new connection into the
500 * SVC_HANDLER. The default behavior delegates to the
501 * <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
503 virtual int connect_svc_handler (SVC_HANDLER
*&sh
,
504 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
505 ACE_Time_Value
*timeout
,
506 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
,
512 * Bridge method for connecting the new connection into the
513 * SVC_HANDLER. The default behavior delegates to the
514 * <PEER_CONNECTOR::connect> in the <Connect_Strategy>.
515 * @a sh_copy is used to obtain a copy of the @a sh pointer, but that
516 * can be kept in the stack; the motivation is a bit too long to
517 * include here, but basically we want to modify @a sh safely, using
518 * the internal locks in the Connect_Strategy, while saving a TSS
519 * copy in @a sh_copy, usually located in the stack.
521 virtual int connect_svc_handler (SVC_HANDLER
*&sh
,
522 SVC_HANDLER
*&sh_copy
,
523 const typename
PEER_CONNECTOR::PEER_ADDR
&remote_addr
,
524 ACE_Time_Value
*timeout
,
525 const typename
PEER_CONNECTOR::PEER_ADDR
&local_addr
,
531 * Bridge method for activating a SVC_HANDLER with the appropriate
532 * concurrency strategy. The default behavior of this method is to
533 * activate the SVC_HANDLER by calling its <open> method (which
534 * allows the SVC_HANDLER to define its own concurrency strategy).
535 * However, subclasses can override this strategy to do more
536 * sophisticated concurrency activations (such as creating the
537 * SVC_HANDLER as an "active object" via multi-threading or
540 virtual int activate_svc_handler (SVC_HANDLER
*svc_handler
);
542 // = Strategy objects.
544 /// Creation strategy for an Connector.
545 CREATION_STRATEGY
*creation_strategy_
;
547 /// True if Connector created the creation strategy and thus should
548 /// delete it, else false.
549 bool delete_creation_strategy_
;
551 /// Connect strategy for a Connector.
552 CONNECT_STRATEGY
*connect_strategy_
;
554 /// True if Connector created the connect strategy and thus should
555 /// delete it, else false.
556 bool delete_connect_strategy_
;
558 /// Concurrency strategy for a Connector.
559 CONCURRENCY_STRATEGY
*concurrency_strategy_
;
561 /// True if Connector created the concurrency strategy and thus should
562 /// delete it, else false.
563 bool delete_concurrency_strategy_
;
566 ACE_END_VERSIONED_NAMESPACE_DECL
568 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
569 #include "ace/Connector.cpp"
570 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
572 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
573 #pragma implementation ("Connector.cpp")
574 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
576 #include /**/ "ace/post.h"
578 #endif /* ACE_CONNECTOR_H */