Public Types | Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | Friends

ACE_Select_Reactor_Handler_Repository Class Reference

Used to map ACE_HANDLEs onto the appropriate ACE_Event_Handler *. More...

#include <Select_Reactor_Base.h>

Collaboration diagram for ACE_Select_Reactor_Handler_Repository:
Collaboration graph
[legend]

List of all members.

Public Types

typedef ACE_HANDLE key_type
typedef ACE_Event_Handlervalue_type
typedef ACE_Array_Base
< value_type
map_type
typedef ACE_HANDLE max_handlep1_type
typedef map_type::size_type size_type

Public Member Functions

 ACE_Select_Reactor_Handler_Repository (ACE_Select_Reactor_Impl &)
 Default "do-nothing" constructor.
int open (size_type size)
 Initialize a repository of the appropriate size.
int close (void)
 Close down the repository.
ACE_Event_Handlerfind (ACE_HANDLE handle)
int bind (ACE_HANDLE, ACE_Event_Handler *, ACE_Reactor_Mask)
int unbind (ACE_HANDLE, ACE_Reactor_Mask mask)
 Remove the binding of ACE_HANDLE in accordance with the mask.
int unbind_all (void)
 Remove all the <ACE_HANDLE, ACE_Event_Handler> tuples.
bool invalid_handle (ACE_HANDLE handle)
bool handle_in_range (ACE_HANDLE handle)
size_type size (void) const
 Returns the current table size.
max_handlep1_type max_handlep1 (void) const
 Maximum ACE_HANDLE value, plus 1.
void dump (void) const
 Dump the state of an object.

Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.

Private Member Functions

int unbind (ACE_HANDLE handle, map_type::iterator pos, ACE_Reactor_Mask mask)
map_type::iterator find_eh (ACE_HANDLE handle)

Private Attributes

ACE_Select_Reactor_Implselect_reactor_
 Reference to our Select_Reactor.
max_handlep1_type max_handlep1_
map_type event_handlers_
 Underlying table of event handlers.

Friends

class ACE_Select_Reactor_Handler_Repository_Iterator

Detailed Description

Used to map ACE_HANDLEs onto the appropriate ACE_Event_Handler *.

This class is necessary to shield differences between UNIX and Win32. In UNIX, ACE_HANDLE is an int, whereas in Win32 it's a void *. This class hides all these details from the bulk of the ACE_Select_Reactor code. All of these methods are called with the main <Select_Reactor> token lock held.

Definition at line 287 of file Select_Reactor_Base.h.


Member Typedef Documentation

Definition at line 292 of file Select_Reactor_Base.h.

The UNIX version implements this via a dynamically allocated array of ACE_Event_Handler* that is indexed directly using the ACE_HANDLE value.

Definition at line 316 of file Select_Reactor_Base.h.

Definition at line 317 of file Select_Reactor_Base.h.

Definition at line 320 of file Select_Reactor_Base.h.

Definition at line 293 of file Select_Reactor_Base.h.


Constructor & Destructor Documentation

ACE_Select_Reactor_Handler_Repository::ACE_Select_Reactor_Handler_Repository ( ACE_Select_Reactor_Impl select_reactor  ) 

Default "do-nothing" constructor.

Definition at line 112 of file Select_Reactor_Base.cpp.

  : select_reactor_ (select_reactor),
#ifndef ACE_WIN32
    max_handlep1_ (0),
#endif  /* !ACE_WIN32 */
    event_handlers_ ()
{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::ACE_Select_Reactor_Handler_Repository");
}


Member Function Documentation

int ACE_Select_Reactor_Handler_Repository::bind ( ACE_HANDLE  handle,
ACE_Event_Handler event_handler,
ACE_Reactor_Mask  mask 
)

Bind the ACE_Event_Handler * to the ACE_HANDLE with the appropriate ACE_Reactor_Mask settings.

Definition at line 193 of file Select_Reactor_Base.cpp.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::bind");

  if (event_handler == 0)
    return -1;

  if (handle == ACE_INVALID_HANDLE)
    handle = event_handler->get_handle ();

  if (this->invalid_handle (handle))
    return -1;

  // Is this handle already in the Reactor?
  bool existing_handle = false;

#if defined (ACE_WIN32)

  map_type::ENTRY * entry = 0;

  int const result =
    this->event_handlers_.bind (handle, event_handler, entry);

  if (result == -1)
    {
      return -1;
    }
  else if (result == 1)  // Entry already exists.
    {
      // Cannot use a different handler for an existing handle.
      if (event_handler != entry->item ())
        {
          return -1;
        }
      else
        {
          // Remember that this handle is already registered in the
          // Reactor.
          existing_handle = true;
        }
    }

#else

  // Check if this handle is already registered.
  ACE_Event_Handler * const current_handler =
    this->event_handlers_[handle];

  if (current_handler)
    {
      // Cannot use a different handler for an existing handle.
      if (current_handler != event_handler)
        return -1;

      // Remember that this handle is already registered in the
      // Reactor.
      existing_handle = true;
    }

  this->event_handlers_[handle] = event_handler;

  if (this->max_handlep1_ < handle + 1)
    this->max_handlep1_ = handle + 1;

#endif /* ACE_WIN32 */

  if (this->select_reactor_.is_suspended_i (handle))
    {
      this->select_reactor_.bit_ops (handle,
                                     mask,
                                     this->select_reactor_.suspend_set_,
                                     ACE_Reactor::ADD_MASK);
    }
  else
    {
      this->select_reactor_.bit_ops (handle,
                                     mask,
                                     this->select_reactor_.wait_set_,
                                     ACE_Reactor::ADD_MASK);

      // Note the fact that we've changed the state of the <wait_set_>,
      // which is used by the dispatching loop to determine whether it can
      // keep going or if it needs to reconsult select().
      // this->select_reactor_.state_changed_ = 1;
    }

  // If new entry, call add_reference() if needed.
  if (!existing_handle)
    event_handler->add_reference ();

  return 0;
}

int ACE_Select_Reactor_Handler_Repository::close ( void   ) 

Close down the repository.

Definition at line 164 of file Select_Reactor_Base.cpp.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::close");

  return this->unbind_all ();
}

void ACE_Select_Reactor_Handler_Repository::dump ( void   )  const

Dump the state of an object.

Definition at line 496 of file Select_Reactor_Base.cpp.

{
#if defined (ACE_HAS_DUMP)
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::dump");

# ifdef ACE_WIN32
#  define ACE_HANDLE_FORMAT_SPECIFIER ACE_TEXT("%@")
#  define ACE_MAX_HANDLEP1_FORMAT_SPECIFIER ACE_TEXT("%u")
# else
#  define ACE_HANDLE_FORMAT_SPECIFIER ACE_TEXT("%d")
#  define ACE_MAX_HANDLEP1_FORMAT_SPECIFIER ACE_TEXT("%d")
# endif  /* ACE_WIN32 */

  ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("max_handlep1_ = ")
              ACE_MAX_HANDLEP1_FORMAT_SPECIFIER
              ACE_TEXT ("\n"),
              this->max_handlep1 ()));
  ACE_DEBUG ((LM_DEBUG,  ACE_TEXT ("[")));

  ACE_Event_Handler *event_handler = 0;

  for (ACE_Select_Reactor_Handler_Repository_Iterator iter (this);
       iter.next (event_handler) != 0;
       iter.advance ())
    ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT (" (event_handler = %@,")
                ACE_TEXT (" event_handler->handle_ = ")
                ACE_HANDLE_FORMAT_SPECIFIER
                ACE_TEXT ("\n"),
                event_handler,
                event_handler->get_handle ()));

  ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" ]\n")));
  ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
#endif /* ACE_HAS_DUMP */
}

ACE_Event_Handler * ACE_Select_Reactor_Handler_Repository::find ( ACE_HANDLE  handle  ) 

Return the ACE_Event_Handler* associated with ACE_HANDLE.

Definition at line 44 of file Select_Reactor_Base.inl.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::find");

  ACE_Event_Handler * eh = 0;

  if (this->handle_in_range (handle))
    {
      map_type::iterator const pos = this->find_eh (handle);

      if (pos != this->event_handlers_.end ())
        {
#ifdef ACE_WIN32
          eh = (*pos).item ();
#else
          eh = *pos;
#endif  /* ACE_WIN32 */
        }
    }
  // Don't bother setting errno.  It isn't used in the select()-based
  // reactors and incurs a TSS access.
  //   else
  //     {
  //       errno = ENOENT;
  //     }

  return eh;
}

ACE_Select_Reactor_Handler_Repository::map_type::iterator ACE_Select_Reactor_Handler_Repository::find_eh ( ACE_HANDLE  handle  )  [private]
Returns:
iterator corresponding ACE_Event_Handler* associated with ACE_HANDLE.

Definition at line 172 of file Select_Reactor_Base.cpp.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::find_eh");

  map_type::iterator pos (this->event_handlers_.end ());

  // this code assumes the handle is in range.
#if defined (ACE_WIN32)
  this->event_handlers_.find (handle, pos);
#else
  map_type::iterator const tmp = &this->event_handlers_[handle];

  if (*tmp != 0)
    pos = tmp;
#endif /* ACE_WIN32 */

  return pos;
}

bool ACE_Select_Reactor_Handler_Repository::handle_in_range ( ACE_HANDLE  handle  ) 

Definition at line 64 of file Select_Reactor_Base.cpp.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::handle_in_range");
#if defined (ACE_WIN32)
  // It's too expensive to perform more exhaustive validity checks on
  // Win32 due to the way that they implement SOCKET HANDLEs.
  if (handle != ACE_INVALID_HANDLE)
#else /* !ACE_WIN32 */
  if (handle >= 0 && handle < this->max_handlep1_)
#endif /* ACE_WIN32 */
    {
      return true;
    }

  // Don't bother setting errno.  It isn't used in the select()-based
  // reactors and incurs a TSS access.
  // errno = EINVAL;

  return false;
}

bool ACE_Select_Reactor_Handler_Repository::invalid_handle ( ACE_HANDLE  handle  ) 

Definition at line 42 of file Select_Reactor_Base.cpp.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::invalid_handle");
#if defined (ACE_WIN32)
  // It's too expensive to perform more exhaustive validity checks on
  // Win32 due to the way that they implement SOCKET HANDLEs.
  if (handle == ACE_INVALID_HANDLE)
#else /* !ACE_WIN32 */
  if (handle < 0
      || static_cast<size_type> (handle) >= this->event_handlers_.size ())
#endif /* ACE_WIN32 */
    {
      errno = EINVAL;
      return true;
    }

  return false;
}

ACE_Select_Reactor_Handler_Repository::max_handlep1_type ACE_Select_Reactor_Handler_Repository::max_handlep1 ( void   )  const

Maximum ACE_HANDLE value, plus 1.

Definition at line 20 of file Select_Reactor_Base.inl.

{
#ifdef ACE_WIN32
  return this->event_handlers_.current_size ();
#else
  return this->max_handlep1_;
#endif  /* ACE_WIN32 */
}

int ACE_Select_Reactor_Handler_Repository::open ( size_type  size  ) 

Initialize a repository of the appropriate size.

On Unix platforms, the size parameter should be as large as the maximum number of file descriptors allowed for a given process. This is necessary since a file descriptor is used to directly index the array of event handlers maintained by the Reactor's handler repository. Direct indexing is used for efficiency reasons.

Definition at line 86 of file Select_Reactor_Base.cpp.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::open");

#if defined (ACE_WIN32)
  if (this->event_handlers_.open (size) == -1)
    return -1;
#else
  if (this->event_handlers_.size (size) == -1)
    return -1;

  // Initialize the ACE_Event_Handler pointers to 0.
  std::fill (this->event_handlers_.begin (),
             this->event_handlers_.end (),
             static_cast<ACE_Event_Handler *> (0));

  this->max_handlep1_ = 0;
#endif /* ACE_WIN32 */

  // Try to increase the number of handles if <size> is greater than
  // the current limit.
  return ACE::set_handle_limit (static_cast<int> (size), 1);
}

ACE_Select_Reactor_Handler_Repository::size_type ACE_Select_Reactor_Handler_Repository::size ( void   )  const

Returns the current table size.

Definition at line 10 of file Select_Reactor_Base.inl.

{
#ifdef ACE_WIN32
  return this->event_handlers_.total_size ();
#else
  return this->event_handlers_.size ();
#endif  /* ACE_WIN32 */
}

int ACE_Select_Reactor_Handler_Repository::unbind ( ACE_HANDLE  handle,
ACE_Reactor_Mask  mask 
)

Remove the binding of ACE_HANDLE in accordance with the mask.

Definition at line 30 of file Select_Reactor_Base.inl.

{
  // Do not refactor this code to optimize the call to the unbind impl.
  // To resolve bug 2653, unbind must be called even when find_eh returns
  // event_handlers_.end().

  return !this->handle_in_range (handle) ? -1
          : this->unbind (handle,
                          this->find_eh (handle),
                          mask);
}

int ACE_Select_Reactor_Handler_Repository::unbind ( ACE_HANDLE  handle,
map_type::iterator  pos,
ACE_Reactor_Mask  mask 
) [private]

Remove the binding of handle corresponding to position pos in accordance with the mask.

Definition at line 291 of file Select_Reactor_Base.cpp.

{
  ACE_TRACE ("ACE_Select_Reactor_Handler_Repository::unbind");

  // Retrieve event handler before unbinding it from the map.  The
  // iterator pointing to it will no longer be valid once the handler
  // is unbound.
  ACE_Event_Handler * const event_handler =
    (pos == this->event_handlers_.end ()
     ? 0
     : ACE_SELECT_REACTOR_EVENT_HANDLER (pos));

  // Clear out the <mask> bits in the Select_Reactor's wait_set.
  this->select_reactor_.bit_ops (handle,
                                 mask,
                                 this->select_reactor_.wait_set_,
                                 ACE_Reactor::CLR_MASK);

  // And suspend_set.
  this->select_reactor_.bit_ops (handle,
                                 mask,
                                 this->select_reactor_.suspend_set_,
                                 ACE_Reactor::CLR_MASK);

  // Note the fact that we've changed the state of the <wait_set_>,
  // which is used by the dispatching loop to determine whether it can
  // keep going or if it needs to reconsult select().
  // this->select_reactor_.state_changed_ = 1;

  // If there are no longer any outstanding events on this <handle>
  // then we can totally shut down the Event_Handler.

  bool const has_any_wait_mask =
    (this->select_reactor_.wait_set_.rd_mask_.is_set (handle)
     || this->select_reactor_.wait_set_.wr_mask_.is_set (handle)
     || this->select_reactor_.wait_set_.ex_mask_.is_set (handle));
  bool const has_any_suspend_mask =
    (this->select_reactor_.suspend_set_.rd_mask_.is_set (handle)
     || this->select_reactor_.suspend_set_.wr_mask_.is_set (handle)
     || this->select_reactor_.suspend_set_.ex_mask_.is_set (handle));

  bool complete_removal = false;

  if (!has_any_wait_mask && !has_any_suspend_mask)
    {
#if defined (ACE_WIN32)
      if (event_handler != 0 && this->event_handlers_.unbind (pos) == -1)
        return -1;  // Should not happen!
#else
      this->event_handlers_[handle] = 0;

      if (this->max_handlep1_ == handle + 1)
        {
          // We've deleted the last entry, so we need to figure out
          // the last valid place in the array that is worth looking
          // at.
          ACE_HANDLE const wait_rd_max =
            this->select_reactor_.wait_set_.rd_mask_.max_set ();
          ACE_HANDLE const wait_wr_max =
            this->select_reactor_.wait_set_.wr_mask_.max_set ();
          ACE_HANDLE const wait_ex_max =
            this->select_reactor_.wait_set_.ex_mask_.max_set ();

          ACE_HANDLE const suspend_rd_max =
            this->select_reactor_.suspend_set_.rd_mask_.max_set ();
          ACE_HANDLE const suspend_wr_max =
            this->select_reactor_.suspend_set_.wr_mask_.max_set ();
          ACE_HANDLE const suspend_ex_max =
            this->select_reactor_.suspend_set_.ex_mask_.max_set ();

          // Compute the maximum of six values.
          this->max_handlep1_ = wait_rd_max;
          if (this->max_handlep1_ < wait_wr_max)
            this->max_handlep1_ = wait_wr_max;
          if (this->max_handlep1_ < wait_ex_max)
            this->max_handlep1_ = wait_ex_max;

          if (this->max_handlep1_ < suspend_rd_max)
            this->max_handlep1_ = suspend_rd_max;
          if (this->max_handlep1_ < suspend_wr_max)
            this->max_handlep1_ = suspend_wr_max;
          if (this->max_handlep1_ < suspend_ex_max)
            this->max_handlep1_ = suspend_ex_max;

          ++this->max_handlep1_;
        }

#endif /* ACE_WIN32 */

      // The handle has been completely removed.
      complete_removal = true;
    }

  if (event_handler == 0)
    return -1;

  bool const requires_reference_counting =
    event_handler->reference_counting_policy ().value () ==
    ACE_Event_Handler::Reference_Counting_Policy::ENABLED;

  // Close down the <Event_Handler> unless we've been instructed not
  // to.
  if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::DONT_CALL) == 0)
    (void) event_handler->handle_close (handle, mask);

  // Call remove_reference() if the removal is complete and reference
  // counting is needed.
  if (complete_removal && requires_reference_counting)
    {
      (void) event_handler->remove_reference ();
    }

  return 0;
}

int ACE_Select_Reactor_Handler_Repository::unbind_all ( void   ) 

Remove all the <ACE_HANDLE, ACE_Event_Handler> tuples.

Definition at line 123 of file Select_Reactor_Base.cpp.

{
  // Unbind all of the <handle, ACE_Event_Handler>s.
#ifdef ACE_WIN32
  map_type::iterator const end = this->event_handlers_.end ();
  for (map_type::iterator pos = this->event_handlers_.begin ();
       pos != end;
       )
    {
      // Post-increment (*not* pre-increment) before unbind()ing since
      // the current iterator will be invalidated during the unbind()
      // operation.
      map_type::iterator const the_pos (pos++);

      ACE_HANDLE const handle = (*the_pos).key ();
      (void) this->unbind (handle,
                           the_pos,
                           ACE_Event_Handler::ALL_EVENTS_MASK);
    }
#else
  // We could use the "end()" iterator but leveraging max_handlep1_
  // allows us to optimize away unnecessary accesses of nil event
  // handler pointers.
  map_type::iterator pos =
    this->event_handlers_.begin ();  // iterator == ACE_Event_Handler*

  for (ACE_HANDLE handle = 0;
       handle < this->max_handlep1_;
       ++handle)
    {
      (void) this->unbind (handle,
                           pos,
                           ACE_Event_Handler::ALL_EVENTS_MASK);
      ++pos;
    }
#endif  /* ACE_WIN32 */

  return 0;
}


Friends And Related Function Documentation

Definition at line 290 of file Select_Reactor_Base.h.


Member Data Documentation

Declare the dynamic allocation hooks.

Definition at line 382 of file Select_Reactor_Base.h.

Underlying table of event handlers.

Definition at line 409 of file Select_Reactor_Base.h.

The highest currently active handle, plus 1 (ranges between 0 and max_size_.

Definition at line 405 of file Select_Reactor_Base.h.

Reference to our Select_Reactor.

Definition at line 400 of file Select_Reactor_Base.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines