Document return values
[ACE_TAO.git] / ACE / ace / Connector.cpp
blob4e7f83b36873c23ee3d66dbcc8dcea6d696656e3
1 #ifndef ACE_CONNECTOR_CPP
2 #define ACE_CONNECTOR_CPP
4 #include "ace/Connector.h"
5 #include "ace/ACE.h"
6 #include "ace/OS_NS_stdio.h"
7 #include "ace/OS_NS_string.h"
8 #include "ace/os_include/os_fcntl.h" /* Has ACE_NONBLOCK */
10 #if !defined (ACE_LACKS_PRAGMA_ONCE)
11 # pragma once
12 #endif /* ACE_LACKS_PRAGMA_ONCE */
14 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
16 ACE_ALLOC_HOOK_DEFINE_Tc (ACE_NonBlocking_Connect_Handler)
17 ACE_ALLOC_HOOK_DEFINE_Tco (ACE_Connector)
18 ACE_ALLOC_HOOK_DEFINE_Tco (ACE_Strategy_Connector)
20 template <typename SVC_HANDLER>
21 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler (ACE_Connector_Base<SVC_HANDLER> &connector,
22 SVC_HANDLER *sh,
23 long id)
24 : connector_ (connector),
25 svc_handler_ (sh),
26 cleanup_svc_handler_ (0),
27 timer_id_ (id)
29 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler");
31 this->reference_counting_policy ().value
32 (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
34 if (this->svc_handler_ != 0 &&
35 this->svc_handler_->reference_counting_policy ().value () ==
36 ACE_Event_Handler::Reference_Counting_Policy::ENABLED)
38 // If SVC_HANDLER is reference counted then NBCH holds a reference
39 // in cleanup_svc_handle_ which is both a pointer to SVC_HANDLER
40 // and a flag that triggers remove_reference in NBCH destructor.
41 this->cleanup_svc_handler_ = sh;
42 this->cleanup_svc_handler_->add_reference ();
46 template <typename SVC_HANDLER>
47 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::~ACE_NonBlocking_Connect_Handler ()
49 if (this->cleanup_svc_handler_)
50 this->cleanup_svc_handler_->remove_reference ();
53 template <typename SVC_HANDLER> SVC_HANDLER *
54 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler ()
56 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler");
57 return this->svc_handler_;
60 template <typename SVC_HANDLER> long
61 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id ()
63 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id");
64 return this->timer_id_;
67 template <typename SVC_HANDLER> void
68 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id (long id)
70 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id");
71 this->timer_id_ = id;
74 template <typename SVC_HANDLER> void
75 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump () const
77 #if defined (ACE_HAS_DUMP)
78 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump");
80 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
81 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("svc_handler_ = %x"), this->svc_handler_));
82 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_id_ = %d"), this->timer_id_));
83 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
84 #endif /* ACE_HAS_DUMP */
87 template <typename SVC_HANDLER> bool
88 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::close (SVC_HANDLER *&sh)
90 // Make sure that we haven't already initialized the Svc_Handler.
91 if (!this->svc_handler_)
92 return false;
95 // Exclusive access to the Reactor.
96 ACE_GUARD_RETURN (ACE_Lock,
97 ace_mon,
98 this->reactor ()->lock (),
99 0);
101 // Double check.
102 if (!this->svc_handler_)
103 return false;
105 // Remember the Svc_Handler.
106 sh = this->svc_handler_;
107 ACE_HANDLE const h = sh->get_handle ();
108 this->svc_handler_ = 0;
110 // Remove this handle from the set of non-blocking handles
111 // in the Connector.
112 this->connector_.non_blocking_handles ().remove (h);
114 // Cancel timer.
115 if (this->reactor ()->cancel_timer (this->timer_id (),
117 0) == -1)
118 return false;
120 // Remove from Reactor.
121 if (-1 == this->reactor ()->remove_handler (
123 ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL))
124 return false;
127 return true;
131 template <typename SVC_HANDLER> int
132 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout
133 (const ACE_Time_Value &tv,
134 const void *arg)
136 // This method is called if a connection times out before completing.
137 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout");
139 SVC_HANDLER *svc_handler = 0;
140 int const retval = this->close (svc_handler) ? 0 : -1;
142 // Forward to the SVC_HANDLER the <arg> that was passed in as a
143 // magic cookie during ACE_Connector::connect(). This gives the
144 // SVC_HANDLER an opportunity to take corrective action (e.g., wait
145 // a few milliseconds and try to reconnect again.
146 if (svc_handler != 0 && svc_handler->handle_timeout (tv, arg) == -1)
147 svc_handler->handle_close (svc_handler->get_handle (),
148 ACE_Event_Handler::TIMER_MASK);
150 return retval;
154 template <typename SVC_HANDLER> int
155 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input (ACE_HANDLE)
157 // Called when a failure occurs during asynchronous connection
158 // establishment.
159 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input");
161 SVC_HANDLER *svc_handler = 0;
162 int const retval = this->close (svc_handler) ? 0 : -1;
164 // Close Svc_Handler.
165 if (svc_handler != 0)
167 svc_handler->close (NORMAL_CLOSE_OPERATION);
170 return retval;
173 template <typename SVC_HANDLER> int
174 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_close (ACE_HANDLE handle,
175 ACE_Reactor_Mask m)
177 // epoll on Linux will, at least sometimes, return EPOLLERR when a connect
178 // fails, triggering a total removal from the reactor. This is different from
179 // select()-based systems which select the fd for read on a connect failure.
180 // So just call handle_input() to rejoin common handling for a failed
181 // connect.
182 if (m == ACE_Event_Handler::ALL_EVENTS_MASK)
183 return this->handle_input (handle);
184 return -1;
187 template <typename SVC_HANDLER> int
188 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output (ACE_HANDLE handle)
190 // Called when a connection is establishment asynchronous.
191 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output");
193 // Grab the connector ref before smashing ourselves in close().
194 ACE_Connector_Base<SVC_HANDLER> &connector = this->connector_;
195 SVC_HANDLER *svc_handler = 0;
196 int const retval = this->close (svc_handler) ? 0 : -1;
198 if (svc_handler != 0)
200 connector.initialize_svc_handler (handle, svc_handler);
203 return retval;
206 template <typename SVC_HANDLER> int
207 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception (ACE_HANDLE h)
209 // On Win32, the except mask must also be set for asynchronous
210 // connects.
211 ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception");
212 return this->handle_output (h);
215 template <typename SVC_HANDLER> int
216 ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::resume_handler ()
218 return ACE_Event_Handler::ACE_EVENT_HANDLER_NOT_RESUMED;
221 template <typename SVC_HANDLER, typename PEER_CONNECTOR> void
222 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::dump () const
224 #if defined (ACE_HAS_DUMP)
225 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::dump");
227 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
228 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = %d"), this->flags_));
229 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
230 #endif /* ACE_HAS_DUMP */
233 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
234 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::make_svc_handler (SVC_HANDLER *&sh)
236 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::make_svc_handler");
238 if (sh == 0)
239 ACE_NEW_RETURN (sh,
240 SVC_HANDLER,
241 -1);
243 // Set the reactor of the newly created <SVC_HANDLER> to the same
244 // reactor that this <Connector> is using.
245 sh->reactor (this->reactor ());
246 return 0;
249 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
250 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::activate_svc_handler (SVC_HANDLER *svc_handler)
252 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::activate_svc_handler");
253 // No errors initially
254 bool error = false;
256 // See if we should enable non-blocking I/O on the <svc_handler>'s
257 // peer.
258 if (ACE_BIT_ENABLED (this->flags_, ACE_NONBLOCK) != 0)
260 if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
261 error = true;
263 // Otherwise, make sure it's disabled by default.
264 else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
265 error = true;
267 // We are connected now, so try to open things up.
268 if (error || svc_handler->open ((void *) this) == -1)
270 // Make sure to close down the <svc_handler> to avoid descriptor
271 // leaks.
272 // The connection was already made; so this close is a "normal"
273 // close operation.
274 svc_handler->close (NORMAL_CLOSE_OPERATION);
275 return -1;
277 else
278 return 0;
281 template <typename SVC_HANDLER, typename PEER_CONNECTOR> PEER_CONNECTOR &
282 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connector () const
284 return const_cast<PEER_CONNECTOR &> (this->connector_);
287 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
288 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_svc_handler
289 (SVC_HANDLER *&svc_handler,
290 const typename PEER_CONNECTOR::PEER_ADDR &remote_addr,
291 ACE_Time_Value *timeout,
292 const typename PEER_CONNECTOR::PEER_ADDR &local_addr,
293 int reuse_addr,
294 int flags,
295 int perms)
297 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_svc_handler");
299 return this->connector_.connect (svc_handler->peer (),
300 remote_addr,
301 timeout,
302 local_addr,
303 reuse_addr,
304 flags,
305 perms);
308 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
309 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_svc_handler
310 (SVC_HANDLER *&svc_handler,
311 SVC_HANDLER *&sh_copy,
312 const typename PEER_CONNECTOR::PEER_ADDR &remote_addr,
313 ACE_Time_Value *timeout,
314 const typename PEER_CONNECTOR::PEER_ADDR &local_addr,
315 int reuse_addr,
316 int flags,
317 int perms)
319 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_svc_handler");
321 sh_copy = svc_handler;
322 return this->connector_.connect (svc_handler->peer (),
323 remote_addr,
324 timeout,
325 local_addr,
326 reuse_addr,
327 flags,
328 perms);
331 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
332 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::open (ACE_Reactor *r, int flags)
334 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::open");
335 this->reactor (r);
336 this->flags_ = flags;
337 return 0;
340 template <typename SVC_HANDLER, typename PEER_CONNECTOR>
341 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::ACE_Connector (ACE_Reactor *r, int flags)
343 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::ACE_Connector");
344 (void) this->open (r, flags);
347 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
348 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect
349 (SVC_HANDLER *&sh,
350 const typename PEER_CONNECTOR::PEER_ADDR &remote_addr,
351 const ACE_Synch_Options &synch_options,
352 const typename PEER_CONNECTOR::PEER_ADDR &local_addr,
353 int reuse_addr,
354 int flags,
355 int perms)
357 // Initiate connection to peer.
358 return this->connect_i (sh,
360 remote_addr,
361 synch_options,
362 local_addr,
363 reuse_addr,
364 flags,
365 perms);
368 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
369 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect
370 (SVC_HANDLER *&sh,
371 SVC_HANDLER *&sh_copy,
372 const typename PEER_CONNECTOR::PEER_ADDR &remote_addr,
373 const ACE_Synch_Options &synch_options,
374 const typename PEER_CONNECTOR::PEER_ADDR &local_addr,
375 int reuse_addr,
376 int flags,
377 int perms)
379 // Initiate connection to peer.
380 return this->connect_i (sh,
381 &sh_copy,
382 remote_addr,
383 synch_options,
384 local_addr,
385 reuse_addr,
386 flags,
387 perms);
390 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
391 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_i
392 (SVC_HANDLER *&sh,
393 SVC_HANDLER **sh_copy,
394 const typename PEER_CONNECTOR::PEER_ADDR &remote_addr,
395 const ACE_Synch_Options &synch_options,
396 const typename PEER_CONNECTOR::PEER_ADDR &local_addr,
397 int reuse_addr,
398 int flags,
399 int perms)
401 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_i");
403 // If the user hasn't supplied us with a <SVC_HANDLER> we'll use the
404 // factory method to create one. Otherwise, things will remain as
405 // they are...
406 if (this->make_svc_handler (sh) == -1)
407 return -1;
409 ACE_Time_Value *timeout = 0;
410 int const use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];
412 if (use_reactor)
413 timeout = const_cast<ACE_Time_Value *> (&ACE_Time_Value::zero);
414 else
415 timeout = const_cast<ACE_Time_Value *> (synch_options.time_value ());
417 int result;
418 if (sh_copy == 0)
419 result = this->connect_svc_handler (sh,
420 remote_addr,
421 timeout,
422 local_addr,
423 reuse_addr,
424 flags,
425 perms);
426 else
427 result = this->connect_svc_handler (sh,
428 *sh_copy,
429 remote_addr,
430 timeout,
431 local_addr,
432 reuse_addr,
433 flags,
434 perms);
436 // Activate immediately if we are connected.
437 if (result != -1)
438 return this->activate_svc_handler (sh);
440 // Delegate to connection strategy.
441 if (use_reactor && ACE_OS::last_error () == EWOULDBLOCK)
443 // If the connection hasn't completed and we are using
444 // non-blocking semantics then register
445 // ACE_NonBlocking_Connect_Handler with the ACE_Reactor so that
446 // it will call us back when the connection is complete or we
447 // timeout, whichever comes first...
448 if (sh_copy == 0)
449 result = this->nonblocking_connect (sh, synch_options);
450 else
451 result = this->nonblocking_connect (*sh_copy, synch_options);
453 // If for some reason the <nonblocking_connect> call failed, then <errno>
454 // will be set to the new error. If the call succeeds, however,
455 // we need to make sure that <errno> remains set to
456 // <EWOULDBLOCK>.
457 if (result == 0)
458 errno = EWOULDBLOCK;
460 else
462 // Save/restore errno.
463 ACE_Errno_Guard error (errno);
464 // Make sure to close down the service handler to avoid handle
465 // leaks.
466 if (sh_copy == 0)
468 if (sh)
469 sh->close (CLOSE_DURING_NEW_CONNECTION);
471 else if (*sh_copy)
472 (*sh_copy)->close (CLOSE_DURING_NEW_CONNECTION);
475 return -1;
478 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
479 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_n
480 (size_t n,
481 SVC_HANDLER *sh[],
482 typename PEER_CONNECTOR::PEER_ADDR remote_addrs[],
483 ACE_TCHAR *failed_svc_handlers,
484 const ACE_Synch_Options &synch_options)
486 int result = 0;
488 for (size_t i = 0; i < n; i++)
490 if (this->connect (sh[i], remote_addrs[i], synch_options) == -1
491 && !(synch_options[ACE_Synch_Options::USE_REACTOR]
492 && errno == EWOULDBLOCK))
494 result = -1;
495 if (failed_svc_handlers != 0)
496 // Mark this entry as having failed.
497 failed_svc_handlers[i] = 1;
499 else if (failed_svc_handlers != 0)
500 // Mark this entry as having succeeded.
501 failed_svc_handlers[i] = 0;
504 return result;
507 // Cancel a <svc_handler> that was started asynchronously.
508 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
509 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::cancel (SVC_HANDLER *sh)
511 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::cancel");
513 ACE_Event_Handler *handler =
514 this->reactor ()->find_handler (sh->get_handle ());
516 if (handler == 0)
517 return -1;
519 // find_handler() increments handler's refcount; ensure we decrement it.
520 ACE_Event_Handler_var safe_handler (handler);
522 NBCH *nbch =
523 dynamic_cast<NBCH *> (handler);
525 if (nbch == 0)
526 return -1;
528 SVC_HANDLER *tmp_sh = 0;
530 if (nbch->close (tmp_sh) == false)
531 return -1;
533 return 0;
536 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
537 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::nonblocking_connect
538 (SVC_HANDLER *sh,
539 const ACE_Synch_Options &synch_options)
541 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::nonblocking_connect");
543 // Must have a valid Reactor for non-blocking connects to work.
544 if (this->reactor () == 0)
545 return -1;
547 // Register the pending SVC_HANDLER so that it can be activated
548 // later on when the connection completes.
550 ACE_HANDLE handle = sh->get_handle ();
551 long timer_id = -1;
552 ACE_Time_Value *tv = 0;
553 NBCH *nbch = 0;
555 ACE_NEW_RETURN (nbch,
556 NBCH (*this,
558 -1),
559 -1);
561 ACE_Event_Handler_var safe_nbch (nbch);
563 // Exclusive access to the Reactor.
564 ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1);
566 // Register handle with the reactor for connection events.
567 ACE_Reactor_Mask const mask = ACE_Event_Handler::CONNECT_MASK;
568 if (this->reactor ()->register_handler (handle,
569 nbch,
570 mask) == -1)
571 goto reactor_registration_failure;
573 // Add handle to non-blocking handle set.
574 this->non_blocking_handles ().insert (handle);
576 // If we're starting connection under timer control then we need to
577 // schedule a timeout with the ACE_Reactor.
578 tv = const_cast<ACE_Time_Value *> (synch_options.time_value ());
579 if (tv != 0)
581 timer_id =
582 this->reactor ()->schedule_timer (nbch,
583 synch_options.arg (),
584 *tv);
585 if (timer_id == -1)
586 goto timer_registration_failure;
588 // Remember timer id.
589 nbch->timer_id (timer_id);
592 return 0;
594 // Undo previous actions using the ol' "goto label and fallthru"
595 // trick...
596 timer_registration_failure:
598 // Remove from Reactor.
599 this->reactor ()->remove_handler (handle, mask);
601 // Remove handle from the set of non-blocking handles.
602 this->non_blocking_handles ().remove (handle);
604 /* FALLTHRU */
606 reactor_registration_failure:
607 // Close the svc_handler
609 sh->close (CLOSE_DURING_NEW_CONNECTION);
611 return -1;
614 template <typename SVC_HANDLER, typename PEER_CONNECTOR>
615 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::~ACE_Connector ()
617 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::~ACE_Connector");
619 this->close ();
622 template <typename SVC_HANDLER, typename PEER_CONNECTOR> void
623 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::initialize_svc_handler
624 (ACE_HANDLE handle,
625 SVC_HANDLER *svc_handler)
627 // Try to find out if the reactor uses event associations for the
628 // handles it waits on. If so we need to reset it.
629 bool const reset_new_handle =
630 this->reactor ()->uses_event_associations ();
632 if (reset_new_handle)
633 this->connector_.reset_new_handle (handle);
635 // Transfer ownership of the ACE_HANDLE to the SVC_HANDLER.
636 svc_handler->set_handle (handle);
638 typename PEER_CONNECTOR::PEER_ADDR raddr;
640 // Check to see if we're connected.
641 if (svc_handler->peer ().get_remote_addr (raddr) != -1)
642 this->activate_svc_handler (svc_handler);
643 else // Somethings gone wrong, so close down...
645 #if defined (ACE_WIN32)
646 // Win32 (at least prior to Windows 2000) has a timing problem.
647 // If you check to see if the connection has completed too fast,
648 // it will fail - so wait 35 milliseconds to let it catch up.
649 ACE_Time_Value tv (0, ACE_NON_BLOCKING_BUG_DELAY);
650 ACE_OS::sleep (tv);
651 if (svc_handler->peer ().get_remote_addr (raddr) != -1)
652 this->activate_svc_handler (svc_handler);
653 else // do the svc handler close below...
654 #endif /* ACE_WIN32 */
655 svc_handler->close (NORMAL_CLOSE_OPERATION);
659 template <typename SVC_HANDLER, typename PEER_CONNECTOR> void
660 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::reactor (ACE_Reactor *reactor)
662 this->reactor_ = reactor;
665 template <typename SVC_HANDLER, typename PEER_CONNECTOR> ACE_Reactor *
666 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::reactor () const
668 return this->reactor_;
671 template <typename SVC_HANDLER, typename PEER_CONNECTOR> ACE_Unbounded_Set<ACE_HANDLE> &
672 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::non_blocking_handles ()
674 return this->non_blocking_handles_;
677 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
678 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::close ()
680 // If there are no non-blocking handle pending, return immediately.
681 if (this->non_blocking_handles ().size () == 0)
682 return 0;
684 // Exclusive access to the Reactor.
685 ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1);
687 // Go through all the non-blocking handles. It is necessary to
688 // create a new iterator each time because we remove from the handle
689 // set when we cancel the Svc_Handler.
690 ACE_HANDLE *handle = 0;
691 while (1)
693 ACE_Unbounded_Set_Iterator<ACE_HANDLE>
694 iterator (this->non_blocking_handles ());
695 if (!iterator.next (handle))
696 break;
698 ACE_Event_Handler *handler =
699 this->reactor ()->find_handler (*handle);
700 if (handler == 0)
702 ACELIB_ERROR ((LM_ERROR,
703 ACE_TEXT ("%t: Connector::close h %d, no handler\n"),
704 *handle));
705 // Remove handle from the set of non-blocking handles.
706 this->non_blocking_handles ().remove (*handle);
707 continue;
710 // find_handler() incremented handler's refcount; ensure it's decremented
711 ACE_Event_Handler_var safe_handler (handler);
712 NBCH *nbch = dynamic_cast<NBCH *> (handler);
713 if (nbch == 0)
715 ACELIB_ERROR ((LM_ERROR,
716 ACE_TEXT ("%t: Connector::close h %d handler %@ ")
717 ACE_TEXT ("not a legit handler\n"),
718 *handle,
719 handler));
720 // Remove handle from the set of non-blocking handles.
721 this->non_blocking_handles ().remove (*handle);
722 continue;
724 SVC_HANDLER *svc_handler = nbch->svc_handler ();
726 // Cancel the non-blocking connection.
727 this->cancel (svc_handler);
729 // Close the associated Svc_Handler.
730 svc_handler->close (NORMAL_CLOSE_OPERATION);
733 return 0;
736 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
737 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::fini ()
739 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::fini");
741 return this->close ();
744 // Hook called by the explicit dynamic linking facility.
746 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
747 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::init (int, ACE_TCHAR *[])
749 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::init");
750 return -1;
753 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
754 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::suspend ()
756 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::suspend");
757 return -1;
760 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
761 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::resume ()
763 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::resume");
764 return -1;
767 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
768 ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::info (ACE_TCHAR **strp, size_t length) const
770 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::info");
771 ACE_TCHAR buf[BUFSIZ];
773 ACE_OS::snprintf (buf, BUFSIZ,
774 ACE_TEXT ("%s\t %s"),
775 ACE_TEXT ("ACE_Connector"),
776 ACE_TEXT ("# connector factory\n"));
778 if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
779 return -1;
780 else
781 ACE_OS::strsncpy (*strp, buf, length);
782 return static_cast<int> (ACE_OS::strlen (buf));
785 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
786 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::open (ACE_Reactor *r,
787 int flags)
789 ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::open");
790 return this->open (r, 0, 0, 0, flags);
793 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
794 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::open
795 (ACE_Reactor *r,
796 ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
797 ACE_Connect_Strategy<SVC_HANDLER, PEER_CONNECTOR> *conn_s,
798 ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
799 int flags)
801 ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::open");
803 this->reactor (r);
805 // @@ Not implemented yet.
806 // this->flags_ = flags;
807 ACE_UNUSED_ARG (flags);
809 // Initialize the creation strategy.
811 // First we decide if we need to clean up.
812 if (this->creation_strategy_ != 0 &&
813 this->delete_creation_strategy_ &&
814 cre_s != 0)
816 delete this->creation_strategy_;
817 this->creation_strategy_ = 0;
818 this->delete_creation_strategy_ = false;
821 if (cre_s != 0)
822 this->creation_strategy_ = cre_s;
823 else if (this->creation_strategy_ == 0)
825 ACE_NEW_RETURN (this->creation_strategy_,
826 CREATION_STRATEGY (0, r),
827 -1);
828 this->delete_creation_strategy_ = true;
832 // Initialize the accept strategy.
834 if (this->connect_strategy_ != 0 &&
835 this->delete_connect_strategy_ &&
836 conn_s != 0)
838 delete this->connect_strategy_;
839 this->connect_strategy_ = 0;
840 this->delete_connect_strategy_ = false;
843 if (conn_s != 0)
844 this->connect_strategy_ = conn_s;
845 else if (this->connect_strategy_ == 0)
847 ACE_NEW_RETURN (this->connect_strategy_,
848 CONNECT_STRATEGY,
849 -1);
850 this->delete_connect_strategy_ = true;
853 // Initialize the concurrency strategy.
855 if (this->concurrency_strategy_ != 0 &&
856 this->delete_concurrency_strategy_ &&
857 con_s != 0)
859 delete this->concurrency_strategy_;
860 this->concurrency_strategy_ = 0;
861 this->delete_concurrency_strategy_ = false;
864 if (con_s != 0)
865 this->concurrency_strategy_ = con_s;
866 else if (this->concurrency_strategy_ == 0)
868 ACE_NEW_RETURN (this->concurrency_strategy_,
869 CONCURRENCY_STRATEGY,
870 -1);
871 this->delete_concurrency_strategy_ = true;
874 return 0;
877 template <typename SVC_HANDLER, typename PEER_CONNECTOR>
878 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::ACE_Strategy_Connector
879 (ACE_Reactor *reactor,
880 ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
881 ACE_Connect_Strategy<SVC_HANDLER, PEER_CONNECTOR> *conn_s,
882 ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
883 int flags)
884 : base_type (reactor),
885 creation_strategy_ (0),
886 delete_creation_strategy_ (false),
887 connect_strategy_ (0),
888 delete_connect_strategy_ (false),
889 concurrency_strategy_ (0),
890 delete_concurrency_strategy_ (false)
892 ACE_TRACE ("ACE_Connector<SVC_HANDLER, PEER_CONNECTOR>::ACE_Strategy_Connector");
894 if (this->open (reactor, cre_s, conn_s, con_s, flags) == -1)
895 ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Strategy_Connector::ACE_Strategy_Connector")));
898 template <typename SVC_HANDLER, typename PEER_CONNECTOR>
899 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::~ACE_Strategy_Connector ()
901 ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::~ACE_Strategy_Connector");
903 // Close down
904 this->close ();
907 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
908 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::close ()
910 if (this->delete_creation_strategy_)
911 delete this->creation_strategy_;
912 this->delete_creation_strategy_ = false;
913 this->creation_strategy_ = 0;
915 if (this->delete_connect_strategy_)
916 delete this->connect_strategy_;
917 this->delete_connect_strategy_ = false;
918 this->connect_strategy_ = 0;
920 if (this->delete_concurrency_strategy_)
921 delete this->concurrency_strategy_;
922 this->delete_concurrency_strategy_ = false;
923 this->concurrency_strategy_ = 0;
925 return SUPER::close ();
928 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
929 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::make_svc_handler (SVC_HANDLER *&sh)
931 return this->creation_strategy_->make_svc_handler (sh);
934 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
935 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_svc_handler
936 (SVC_HANDLER *&sh,
937 const typename PEER_CONNECTOR::PEER_ADDR &remote_addr,
938 ACE_Time_Value *timeout,
939 const typename PEER_CONNECTOR::PEER_ADDR &local_addr,
940 int reuse_addr,
941 int flags,
942 int perms)
944 return this->connect_strategy_->connect_svc_handler (sh,
945 remote_addr,
946 timeout,
947 local_addr,
948 reuse_addr,
949 flags,
950 perms);
953 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
954 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_svc_handler
955 (SVC_HANDLER *&sh,
956 SVC_HANDLER *&sh_copy,
957 const typename PEER_CONNECTOR::PEER_ADDR &remote_addr,
958 ACE_Time_Value *timeout,
959 const typename PEER_CONNECTOR::PEER_ADDR &local_addr,
960 int reuse_addr,
961 int flags,
962 int perms)
964 return this->connect_strategy_->connect_svc_handler (sh,
965 sh_copy,
966 remote_addr,
967 timeout,
968 local_addr,
969 reuse_addr,
970 flags,
971 perms);
974 template <typename SVC_HANDLER, typename PEER_CONNECTOR> int
975 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::activate_svc_handler (SVC_HANDLER *svc_handler)
977 return this->concurrency_strategy_->activate_svc_handler (svc_handler, this);
980 template <typename SVC_HANDLER, typename PEER_CONNECTOR> ACE_Creation_Strategy<SVC_HANDLER> *
981 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::creation_strategy () const
983 return this->creation_strategy_;
986 template <typename SVC_HANDLER, typename PEER_CONNECTOR> ACE_Connect_Strategy<SVC_HANDLER, PEER_CONNECTOR> *
987 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::connect_strategy () const
989 return this->connect_strategy_;
992 template <typename SVC_HANDLER, typename PEER_CONNECTOR> ACE_Concurrency_Strategy<SVC_HANDLER> *
993 ACE_Strategy_Connector<SVC_HANDLER, PEER_CONNECTOR>::concurrency_strategy () const
995 return this->concurrency_strategy_;
998 ACE_END_VERSIONED_NAMESPACE_DECL
1000 #endif /* ACE_CONNECTOR_C */