// Acceptor.cpp,v 4.67 2001/11/23 16:37:08 schmidt Exp

#ifndef ACE_ACCEPTOR_C
#define ACE_ACCEPTOR_C

#include "ace/ACE.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/Acceptor.h"
#include "ace/Handle_Set.h"
#include "ace/WFMO_Reactor.h"

ACE_RCSID(ace, Acceptor, "Acceptor.cpp,v 4.67 2001/11/23 16:37:08 schmidt Exp")

ACE_ALLOC_HOOK_DEFINE(ACE_Acceptor)

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> void
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");

  ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  this->peer_acceptor_.dump ();
  ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR & () const
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR &");
  return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_PEER_ACCEPTOR &
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor (void) const
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor");
  return ACE_const_cast (ACE_PEER_ACCEPTOR &, this->peer_acceptor_);
}

// Returns ACE_HANDLE of the underlying Acceptor_Strategy.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_HANDLE
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle (void) const
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle");
  return this->peer_acceptor_.get_handle ();
}

// Initialize the appropriate strategies for creation, passive
// connection acceptance, and concurrency, and then register <this>
// with the Reactor and listen for connection requests at the
// designated <local_addr>.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open
  (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
   ACE_Reactor *reactor,
   int flags,
   int use_select,
   int reuse_addr)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");
  this->flags_ = flags;
  this->use_select_ = use_select;
  this->reuse_addr_ = reuse_addr;
  this->peer_acceptor_addr_ = local_addr;

  // Must supply a valid Reactor to Acceptor::open()...

  if (reactor == 0)
    {
      errno = EINVAL;
      return -1;
    }

  if (this->peer_acceptor_.open (local_addr, reuse_addr) == -1)
    return -1;

  // Set the peer acceptor's handle into non-blocking mode.  This is a
  // safe-guard against the race condition that can otherwise occur
  // between the time when <select> indicates that a passive-mode
  // socket handle is "ready" and when we call <accept>.  During this
  // interval, the client can shutdown the connection, in which case,
  // the <accept> call can hang!
  this->peer_acceptor_.enable (ACE_NONBLOCK);

  int result = reactor->register_handler (this,
                                          ACE_Event_Handler::ACCEPT_MASK);
  if (result != -1)
    this->reactor (reactor);

  return result;
}

// Simple constructor.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor (ACE_Reactor *reactor,
                                                              int use_select)
  :flags_ (0),
   use_select_ (use_select),
   reuse_addr_ (1)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor");

  this->reactor (reactor);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor
  (const ACE_PEER_ACCEPTOR_ADDR &addr,
   ACE_Reactor *reactor,
   int flags,
   int use_select,
   int reuse_addr)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Acceptor");

  if (this->open (addr,
                  reactor,
                  flags,
                  use_select,
                  reuse_addr) == -1)
    ACE_ERROR ((LM_ERROR,
                ACE_LIB_TEXT ("%p\n"),
                ACE_LIB_TEXT ("ACE_Acceptor::ACE_Acceptor")));
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Acceptor (void)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Acceptor");
  this->handle_close ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini (void)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini");
  return ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close ();
}

// Hook called by the explicit dynamic linking facility.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init (int, ACE_TCHAR *[])
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init");
  return -1;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info (ACE_TCHAR **strp,
                                                      size_t length) const
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info");
  ACE_TCHAR buf[BUFSIZ];
  ACE_TCHAR addr_str[BUFSIZ];
  ACE_PEER_ACCEPTOR_ADDR addr;

  if (this->acceptor ().get_local_addr (addr) == -1)
    return -1;
  else if (addr.addr_to_string (addr_str, sizeof addr_str) == -1)
    return -1;

  ACE_OS::sprintf (buf,
                   ACE_LIB_TEXT ("%s\t %s %s"),
                   ACE_LIB_TEXT ("ACE_Acceptor"),
                   addr_str,
                   ACE_LIB_TEXT ("# acceptor factory\n"));

  if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
    return -1;
  else
    ACE_OS::strsncpy (*strp, buf, length);
  return ACE_OS::strlen (buf);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend (void)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend");
  return this->reactor ()->suspend_handler (this);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume (void)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume");
  return this->reactor ()->resume_handler (this);
}

// Perform termination activities when <this> is removed from the
// <reactor>.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close (void)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close");
  return this->handle_close ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDLE,
                                                              ACE_Reactor_Mask)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close");
  // Guard against multiple closes.
  if (this->reactor () != 0)
    {
      ACE_HANDLE handle = this->get_handle ();

      this->reactor ()->remove_handler
        (handle,
         // We must pass the DONT_CALL flag here to avoid infinite
         // recursion.
         ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);

      // Shut down the listen socket to recycle the handles.
      if (this->peer_acceptor_.close () == -1)
        ACE_ERROR ((LM_ERROR,
                    ACE_LIB_TEXT ("close\n")));
      // Set the Reactor to 0 so that we don't try to close down
      // again.
      this->reactor (0);
    }
  return 0;
}

// Bridge method for creating a SVC_HANDLER.  The strategy for
// creating a SVC_HANDLER are configured into the Acceptor via it's
// <creation_strategy_>.  The default is to create a new SVC_HANDLER.
// However, subclasses can override this strategy 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.).

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler");

  if (sh == 0)
    ACE_NEW_RETURN (sh,
                    SVC_HANDLER,
                    -1);

  // Set the reactor of the newly created <SVC_HANDLER> to the same
  // reactor that this <ACE_Acceptor> is using.
  if (this->reactor ())
    sh->reactor (this->reactor ());

  return 0;
}

// Bridge method for accepting the new connection into the
// <svc_handler>.  The default behavior delegates to the
// <PEER_ACCEPTOR::accept> in the Acceptor_Strategy.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler
  (SVC_HANDLER *svc_handler)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler");

  // Try to find out if the implementation of the reactor that we are
  // using requires us to reset the event association for the newly
  // created handle. This is because the newly created handle will
  // inherit the properties of the listen handle, including its event
  // associations.
  int reset_new_handle = this->reactor ()->uses_event_associations ();

  if (this->acceptor ().accept (svc_handler->peer (), // stream
                                0, // remote address
                                0, // timeout
                                1, // restart
                                reset_new_handle  // reset new handler
                                ) == -1)
    {
      // Close down handler to avoid memory leaks.
      svc_handler->close (0);

      return -1;
    }
  else
    return 0;
}

// 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).

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler
  (SVC_HANDLER *svc_handler)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler");

  int result = 0;

  // See if we should enable non-blocking I/O on the <svc_handler>'s
  // peer.
  if (ACE_BIT_ENABLED (this->flags_,
                       ACE_NONBLOCK))
    {
      if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
        result = -1;
    }
  // Otherwise, make sure it's disabled by default.
  else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
    result = -1;

  if (result == 0 && svc_handler->open ((void *) this) == -1)
    result = -1;

  if (result == -1)
    svc_handler->close (0);

  return result;
}

// Template Method that makes a SVC_HANDLER (using the appropriate
// creation strategy), accept the connection into the SVC_HANDLER, and
// then activate the SVC_HANDLER.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input (ACE_HANDLE listener)
{
  ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input");
  ACE_Handle_Set conn_handle;

  // Default is "timeout (0, 0)," which means "poll."
  ACE_Time_Value timeout;

  // Accept connections from clients.  Note that a loop is used for two
  // reasons:
  //
  // 1. It allows us to accept all pending connections without an
  //    extra trip through the ACE_Reactor and without having to use
  //    non-blocking I/O...
  //
  // 2. It allows the TLI_SAP::ACE_Acceptor class to work correctly (don't
  //    ask -- TLI is *horrible*...).

  // @@ What should we do if any of the substrategies fail?  Right
  // now, we just print out a diagnostic message if <ACE::debug>
  // returns > 0 and return 0 (which means that the Acceptor remains
  // registered with the Reactor)...
  do
    {
      // Create a service handler, using the appropriate creation
      // strategy.

      SVC_HANDLER *svc_handler = 0;

      if (this->make_svc_handler (svc_handler) == -1)
        {
          if (ACE::debug () > 0)
            ACE_DEBUG ((LM_DEBUG,
                        ACE_LIB_TEXT ("%p\n"),
                        ACE_LIB_TEXT ("make_svc_handler")));
          return 0;
        }
      // Accept connection into the Svc_Handler.

      else if (this->accept_svc_handler (svc_handler) == -1)
        {
          if (ACE::debug () > 0)
            ACE_DEBUG ((LM_DEBUG,
                        ACE_LIB_TEXT ("%p\n"),
                        ACE_LIB_TEXT ("accept_svc_handler")));
          return 0;
        }

      // Activate the <svc_handler> using the designated concurrency
      // strategy (note that this method becomes responsible for
      // handling errors and freeing up the memory if things go
      // awry...).
      else if (this->activate_svc_handler (svc_handler) == -1)
        {
          if (ACE::debug () > 0)
            ACE_DEBUG ((LM_DEBUG,
                        ACE_LIB_TEXT ("%p\n"),
                        ACE_LIB_TEXT ("activate_svc_handler")));
          return 0;
        }

      conn_handle.set_bit (listener);
    }

  // Now, check to see if there is another connection pending and
  // break out of the loop if there is none.
  while (this->use_select_
         && ACE_OS::select (int (listener) + 1,
                            conn_handle,
                            0,
                            0,
                            &timeout) == 1);
  return 0;
}

ACE_ALLOC_HOOK_DEFINE(ACE_Strategy_Acceptor)

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend (void)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend");

  // First suspend the SVC_HANDLER's we've created.
  if (this->scheduling_strategy_->suspend () == -1)
    return -1;
  else   // Then suspend ourselves.
    return ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume (void)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume");

  // First resume ourselves.
  if (ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume () == -1)
    return -1;
  else // Then resume the SVC_HANDLER's we've created.
    return this->scheduling_strategy_->resume ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> void
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");

  ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump ();
  this->creation_strategy_->dump ();
  ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_creation_strategy_ = %d"), delete_creation_strategy_));
  this->accept_strategy_->dump ();
  ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_accept_strategy_ = %d"), delete_accept_strategy_));
  this->concurrency_strategy_->dump ();
  ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_concurrency_strategy_ = %d"), delete_concurrency_strategy_));
  this->scheduling_strategy_->dump ();
  ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("delete_scheduling_strategy_ = %d"), delete_scheduling_strategy_));
  ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nservice_name_ = %s"),
              this->service_name_ == 0 ? ACE_LIB_TEXT ("<unknown>") : this->service_name_));
  ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nservice_description_ = %s"),
              this->service_description_ == 0 ? ACE_LIB_TEXT ("<unknown>") : this->service_description_));
  ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nservice_port_ = %d"), this->service_port_));
  this->service_addr_.dump ();
  ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_PEER_ACCEPTOR &
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor (void) const
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor");
  return this->accept_strategy_->acceptor ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR & () const
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR &");
  return this->accept_strategy_->acceptor ();
}

// Returns ACE_HANDLE of the underlying Acceptor_Strategy.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_HANDLE
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle (void) const
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle");
  return this->accept_strategy_->get_handle ();
}

// Initialize the appropriate strategies for creation, passive
// connection acceptance, and concurrency, and then register <this>
// with the Reactor and listen for connection requests at the
// designated <local_addr>.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open
  (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
   ACE_Reactor *reactor,
   ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
   ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> *acc_s,
   ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
   ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,
   const ACE_TCHAR *service_name,
   const ACE_TCHAR *service_description,
   int use_select)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");

  if (this->service_name_ == 0 && service_name != 0)
    ACE_ALLOCATOR_RETURN (this->service_name_,
                          ACE_OS::strdup (service_name),
                          -1);
  if (this->service_description_ == 0 && service_description != 0)
    ACE_ALLOCATOR_RETURN (this->service_description_,
                          ACE_OS::strdup (service_description),
                          -1);
  this->reactor (reactor);

  // Must supply a valid Reactor to Acceptor::open()...
  if (reactor == 0)
    {
      errno = EINVAL;
      return -1;
    }

  // Initialize the creation strategy.

  if (cre_s == 0)
    {
      ACE_NEW_RETURN (cre_s,
                      CREATION_STRATEGY,
                      -1);
      this->delete_creation_strategy_ = 1;
    }
  this->creation_strategy_ = cre_s;

  // Initialize the accept strategy.

  if (acc_s == 0)
    {
      ACE_NEW_RETURN (acc_s,
                      ACCEPT_STRATEGY (this->reactor ()),
                      -1);
      this->delete_accept_strategy_ = 1;
    }
  this->accept_strategy_ = acc_s;

  if (this->accept_strategy_->open (local_addr, 1) == -1)
    return -1;

  // Set the peer acceptor's handle into non-blocking mode.  This is a
  // safe-guard against the race condition that can otherwise occur
  // between the time when <select> indicates that a passive-mode
  // socket handle is "ready" and when we call <accept>.  During this
  // interval, the client can shutdown the connection, in which case,
  // the <accept> call can hang!
  if (this->accept_strategy_->acceptor ().enable (ACE_NONBLOCK) != 0)
    return -1;

  // Initialize the concurrency strategy.

  if (con_s == 0)
    {
      ACE_NEW_RETURN (con_s,
                      CONCURRENCY_STRATEGY,
                      -1);
      this->delete_concurrency_strategy_ = 1;
    }
  this->concurrency_strategy_ = con_s;

  // Initialize the scheduling strategy.

  if (sch_s == 0)
    {
      ACE_NEW_RETURN (sch_s,
                      SCHEDULING_STRATEGY,
                      -1);
      this->delete_scheduling_strategy_ = 1;
    }
  this->scheduling_strategy_ = sch_s;

  this->use_select_ = use_select;

  return this->reactor ()->register_handler
    (this,
     ACE_Event_Handler::ACCEPT_MASK);
}

// Simple constructor.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor
  (const ACE_TCHAR service_name[],
   const ACE_TCHAR service_description[],
   int use_select)
    : creation_strategy_ (0),
      delete_creation_strategy_ (0),
      accept_strategy_ (0),
      delete_accept_strategy_ (0),
      concurrency_strategy_ (0),
      delete_concurrency_strategy_ (0),
      scheduling_strategy_ (0),
      delete_scheduling_strategy_ (0),
      service_name_ (0),
      service_description_ (0),
      service_port_ (0)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor");

  if (service_name != 0)
    ACE_ALLOCATOR (this->service_name_,
                   ACE_OS::strdup (service_name));
  if (service_description != 0)
    ACE_ALLOCATOR (this->service_description_,
                   ACE_OS::strdup (service_description));
  this->use_select_ = use_select;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor
  (const ACE_PEER_ACCEPTOR_ADDR &addr,
   ACE_Reactor *reactor,
   ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
   ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> *acc_s,
   ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
   ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,
   const ACE_TCHAR service_name[],
   const ACE_TCHAR service_description[],
   int use_select)
    : creation_strategy_ (0),
      delete_creation_strategy_ (0),
      accept_strategy_ (0),
      delete_accept_strategy_ (0),
      concurrency_strategy_ (0),
      delete_concurrency_strategy_ (0),
      scheduling_strategy_ (0),
      delete_scheduling_strategy_ (0),
      service_name_ (0),
      service_description_ (0),
      service_port_ (0)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Strategy_Acceptor");

  if (this->open (addr,
                  reactor,
                  cre_s,
                  acc_s,
                  con_s,
                  sch_s,
                  service_name,
                  service_description,
                  use_select) == -1)
    ACE_ERROR ((LM_ERROR,
                ACE_LIB_TEXT ("%p\n"),
                ACE_LIB_TEXT ("ACE_Strategy_Acceptor::ACE_Strategy_Acceptor")));
}

// Perform termination activities when <this> is removed from the
// <ACE_Reactor>.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDLE,
                                                                       ACE_Reactor_Mask)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close");
  // Guard against multiple closes.
  if (this->reactor () != 0)
    {
      ACE_HANDLE handle = this->get_handle ();

      if (this->delete_creation_strategy_)
        delete this->creation_strategy_;
      this->delete_creation_strategy_ = 0;
      this->creation_strategy_ = 0;

      if (this->delete_accept_strategy_)
        delete this->accept_strategy_;
      this->delete_accept_strategy_ = 0;
      this->accept_strategy_ = 0;

      if (this->delete_concurrency_strategy_)
        delete this->concurrency_strategy_;
      this->delete_concurrency_strategy_ = 0;
      this->concurrency_strategy_ = 0;

      if (this->delete_scheduling_strategy_)
        delete this->scheduling_strategy_;
      this->delete_scheduling_strategy_ = 0;
      this->scheduling_strategy_ = 0;

      // We must use the <handle> obtained *before* we deleted the
      // accept_strategy_...

      this->reactor ()->remove_handler
        (handle,
         ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);

      // Set the Reactor to 0 so that we don't try to close down
      // again.
      this->reactor (0);
    }
  return 0;
}

// Bridge method for creating a <SVC_HANDLER>.  The strategy for
// creating a <SVC_HANDLER> are configured into the Acceptor via it's
// <creation_strategy_>.  The default is to create a new
// <SVC_HANDLER>.  However, subclasses can override this strategy 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.).

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::make_svc_handler");
  return this->creation_strategy_->make_svc_handler (sh);
}

// Bridge method for accepting the new connection into the
// <svc_handler>.  The default behavior delegates to the
// <Strategy_Acceptor::accept> in the Acceptor_Strategy.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler
  (SVC_HANDLER *svc_handler)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept_svc_handler");
  return this->accept_strategy_->accept_svc_handler (svc_handler);
}

// 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).

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler
  (SVC_HANDLER *svc_handler)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler");
  return this->concurrency_strategy_->activate_svc_handler
    (svc_handler,
     (void *) this);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Strategy_Acceptor (void)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Strategy_Acceptor");
  ACE_OS::free ((void *) this->service_name_);
  ACE_OS::free ((void *) this->service_description_);
  this->handle_close ();
}

// Signal the server to shutdown gracefully.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_signal (int, siginfo_t *, ucontext_t *)
{
  ACE_Reactor::end_event_loop ();
  return 0;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info (ACE_TCHAR **strp,
                                                               size_t length) const
{
  ACE_TRACE ("ACE_Strategy_Acceptor::info");

  ACE_TCHAR buf[BUFSIZ];
  ACE_TCHAR service_addr_str[BUFSIZ];
  ACE_PEER_ACCEPTOR_ADDR addr;

  if (this->acceptor ().get_local_addr (addr) == -1)
    return -1;
  else if (addr.addr_to_string (service_addr_str,
                                sizeof service_addr_str) == -1)
    return -1;

  // @@ Should add the protocol in...
  ACE_OS::sprintf (buf,
                   ACE_LIB_TEXT ("%s\t %s #%s\n"),
                   this->service_name_ == 0
                   ? ACE_LIB_TEXT ("<unknown>")
                   : this->service_name_,
                   service_addr_str,
                   this->service_description_ == 0
                   ? ACE_LIB_TEXT ("<unknown>")
                   : this->service_description_);

  if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
    return -1;
  else
    ACE_OS::strsncpy (*strp, buf, length);
  return ACE_OS::strlen (buf);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini (void)
{
  ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini");
  return this->ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close ();
}

ACE_ALLOC_HOOK_DEFINE(ACE_Oneshot_Acceptor)

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> void
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump (void) const
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::dump");

  ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("\nsvc_handler_ = %x"), this->svc_handler_));
  ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("\nrestart_ = %d"), this->restart_));
  this->peer_acceptor_.dump ();
  ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("delete_concurrency_strategy_ = %d"),
              delete_concurrency_strategy_));
  this->concurrency_strategy_->dump ();
  ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open
  (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
   ACE_Reactor *reactor,
   ACE_Concurrency_Strategy<SVC_HANDLER> *con_s)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");
  this->reactor (reactor);

  // Initialize the concurrency strategy.

  if (con_s == 0)
    {
      ACE_NEW_RETURN (con_s,
                      ACE_Concurrency_Strategy<SVC_HANDLER>,
                      -1);
      this->delete_concurrency_strategy_ = 1;
    }
  this->concurrency_strategy_ = con_s;

  // Reuse the addr, even if it is already in use...!
  return this->peer_acceptor_.open (local_addr, 1);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor (void)
  : delete_concurrency_strategy_ (0)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor");
  this->reactor (0);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor
  (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
   ACE_Reactor *reactor,
   ACE_Concurrency_Strategy<SVC_HANDLER> *cs)
    : delete_concurrency_strategy_ (0)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::ACE_Oneshot_Acceptor");
  if (this->open (local_addr, reactor, cs) == -1)
    ACE_ERROR ((LM_ERROR,
                ACE_LIB_TEXT ("%p\n"),
                ACE_LIB_TEXT ("ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor")));
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Oneshot_Acceptor (void)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::~ACE_Oneshot_Acceptor");
  this->handle_close ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close (void)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::close");
  return this->handle_close ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDLE,
                                                                      ACE_Reactor_Mask)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close");

  // Guard against multiple closes.
  if (this->delete_concurrency_strategy_)
    {
      delete this->concurrency_strategy_;
      this->delete_concurrency_strategy_ = 0;
      this->concurrency_strategy_ = 0;

      // Note that if we aren't actually registered with the
      // ACE_Reactor then it's ok for this call to fail...

      if (this->reactor ())
        this->reactor ()->remove_handler
          (this,
           ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);

      if (this->peer_acceptor_.close () == -1)
        ACE_ERROR ((LM_ERROR,
                    ACE_LIB_TEXT ("close\n")));
    }
  return 0;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_timeout
  (const ACE_Time_Value &tv,
   const void *arg)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_timeout");
  errno = ETIME;

  if (this->svc_handler_->handle_timeout (tv, arg) == -1)
    this->svc_handler_->handle_close (this->svc_handler_->get_handle (),
                                      ACE_Event_Handler::TIMER_MASK);

  // Since we aren't necessarily registered with the Reactor, don't
  // bother to check the return value here...
  if (this->reactor ())
    this->reactor ()->remove_handler (this,
                                      ACE_Event_Handler::ACCEPT_MASK);
  return 0;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::cancel (void)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::cancel");
  return this->reactor () && this->reactor ()->cancel_timer (this);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::register_handler
  (SVC_HANDLER *svc_handler,
   const ACE_Synch_Options &synch_options,
   int restart)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::register_handler");
  // Can't do this if we don't have a Reactor.
  if (this->reactor () == 0)
    {
      errno = EINVAL;
      return -1;
    }
  else
    {
      this->svc_handler_ = svc_handler;
      this->restart_ = restart;
      ACE_Time_Value *tv = (ACE_Time_Value *) synch_options.time_value ();

      if (tv != 0
          && this->reactor ()->schedule_timer (this,
                                               synch_options.arg (),
                                               *tv) == 0)
        return -1;
      else
        return this->reactor ()->register_handler
          (this,
           ACE_Event_Handler::ACCEPT_MASK);
    }
}

// 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).

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler
  (SVC_HANDLER *svc_handler)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::activate_svc_handler");
  return this->concurrency_strategy_->activate_svc_handler
    (svc_handler,
     (void *) this);
}

// Factors out the code shared between the <accept> and <handle_input>
// methods.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::shared_accept
  (SVC_HANDLER *svc_handler,
   ACE_PEER_ACCEPTOR_ADDR *remote_addr,
   ACE_Time_Value *timeout,
   int restart,
   int reset_new_handle)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::shared_accept");
  if (svc_handler == 0)
    return -1;

  // Accept connection into the Svc_Handler.
  else if (this->peer_acceptor_.accept (svc_handler->peer (), // stream
                                        remote_addr, // remote address
                                        timeout, // timeout
                                        restart, // restart
                                        reset_new_handle // reset new handle
                                        ) == -1)
    {
      // Check whether we just timed out or whether we failed...
      if (!(errno == EWOULDBLOCK || errno == ETIME))
        // Close down handler to avoid memory leaks.
        svc_handler->close (0);
      return -1;
    }
  // Activate the <svc_handler> using the designated concurrency
  // strategy (note that this method becomes responsible for handling
  // errors and freeing up the memory if things go awry...)
  else
    return this->activate_svc_handler (svc_handler);
}

// Make a SVC_HANDLER, accept the connection into the SVC_HANDLER, and
// then activate the SVC_HANDLER.  Note that SVC_HANDLER::open()
// decides what type of concurrency strategy to use.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept
  (SVC_HANDLER *svc_handler,
   ACE_PEER_ACCEPTOR_ADDR *remote_addr,
   const ACE_Synch_Options &synch_options,
   int restart,
   int reset_new_handle)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::accept");
  // Note that if timeout == ACE_Time_Value (x, y) where (x > 0 || y >
  // 0) then this->connector_.connect() will block synchronously.  If
  // <use_reactor> is set then we don't want this to happen (since we
  // want the ACE_Reactor to do the timeout asynchronously).
  // Therefore, we'll force this->connector_ to use ACE_Time_Value (0,
  // 0) in this case...

  ACE_Time_Value *timeout;
  int use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];

  if (use_reactor)
    timeout = (ACE_Time_Value *) &ACE_Time_Value::zero;
  else
    timeout = (ACE_Time_Value *) synch_options.time_value ();

  if (this->shared_accept (svc_handler, // stream
                           remote_addr, // remote address
                           timeout, // timeout
                           restart, // restart
                           reset_new_handle // reset new handler
                           ) == -1)
    {
      if (use_reactor && errno == EWOULDBLOCK)
        // We couldn't accept right away, so let's wait in the
        // <ACE_Reactor>.
        this->register_handler (svc_handler,
                                synch_options,
                                restart);
      return -1;
    }
  return 0;
}

// Accepts one pending connection from a client (since we're the
// "oneshot" Acceptor).

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input (ACE_HANDLE)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_input");
  int result = 0;

  // Cancel any timer that might be pending.
  this->cancel ();

  // Try to find out if the implementation of the reactor that we are
  // using requires us to reset the event association for the newly
  // created handle.  This is because the newly created handle will
  // inherit the properties of the listen handle, including its event
  // associations.
  int reset_new_handle = this->reactor ()->uses_event_associations ();

  // There is a use-case whereby this object will be gone upon return
  // from shared_accept - if the Svc_Handler deletes this Oneshot_Acceptor
  // during the shared_accept/activation steps. So, do whatever we need
  // to do with this object before calling shared_accept.
  if (this->reactor ())
    this->reactor ()->remove_handler
      (this,
       ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);

  if (this->shared_accept (this->svc_handler_, // stream
                           0, // remote address
                           0, // timeout
                           this->restart_, // restart
                           reset_new_handle // reset new handle
                           ) == -1)
    result = -1;

  return result;
}

// Hook called by the explicit dynamic linking facility.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init (int, ACE_TCHAR *[])
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::init");
  return -1;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini (void)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::fini");
  return this->handle_close ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info (ACE_TCHAR **strp,
                                                              size_t length) const
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::info");
  ACE_TCHAR buf[BUFSIZ];
  ACE_TCHAR addr_str[BUFSIZ];
  ACE_PEER_ACCEPTOR_ADDR addr;

  if (this->peer_acceptor_.get_local_addr (addr) == -1)
    return -1;
  else if (addr.addr_to_string (addr_str, sizeof addr_str) == -1)
    return -1;

  ACE_OS::sprintf (buf,
                   ACE_LIB_TEXT ("%s\t %s %s"),
                   ACE_LIB_TEXT ("ACE_Oneshot_Acceptor"),
                   addr_str,
                   ACE_LIB_TEXT ("#oneshot acceptor factory\n"));

  if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
    return -1;
  else
    ACE_OS::strsncpy (*strp, buf, length);
  return ACE_OS::strlen (buf);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend (void)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::suspend");
  return this->reactor () && this->reactor ()->suspend_handler (this);
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume (void)
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::resume");
  return this->reactor () && this->reactor ()->resume_handler (this);
}

// Returns ACE_HANDLE of the underlying peer_acceptor.

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_HANDLE
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle (void) const
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::get_handle");
  return this->peer_acceptor_.get_handle ();
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> ACE_PEER_ACCEPTOR &
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor (void) const
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::acceptor");
  return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_;
}

template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR & () const
{
  ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::operator ACE_PEER_ACCEPTOR &");
  return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_;
}

#endif /* ACE_ACCEPTOR_C */
