asio::error_code signal_set_service::add()

in demo_example/asio/asio/detail/impl/signal_set_service.ipp [308:380]


asio::error_code signal_set_service::add(
    signal_set_service::implementation_type& impl,
    int signal_number, asio::error_code& ec)
{
  // Check that the signal number is valid.
  if (signal_number < 0 || signal_number >= max_signal_number)
  {
    ec = asio::error::invalid_argument;
    return ec;
  }

  signal_state* state = get_signal_state();
  static_mutex::scoped_lock lock(state->mutex_);

  // Find the appropriate place to insert the registration.
  registration** insertion_point = &impl.signals_;
  registration* next = impl.signals_;
  while (next && next->signal_number_ < signal_number)
  {
    insertion_point = &next->next_in_set_;
    next = next->next_in_set_;
  }

  // Only do something if the signal is not already registered.
  if (next == 0 || next->signal_number_ != signal_number)
  {
    registration* new_registration = new registration;

#if defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)
    // Register for the signal if we're the first.
    if (state->registration_count_[signal_number] == 0)
    {
# if defined(ASIO_HAS_SIGACTION)
      using namespace std; // For memset.
      struct sigaction sa;
      memset(&sa, 0, sizeof(sa));
      sa.sa_handler = asio_signal_handler;
      sigfillset(&sa.sa_mask);
      if (::sigaction(signal_number, &sa, 0) == -1)
# else // defined(ASIO_HAS_SIGACTION)
      if (::signal(signal_number, asio_signal_handler) == SIG_ERR)
# endif // defined(ASIO_HAS_SIGACTION)
      {
# if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
        ec = asio::error::invalid_argument;
# else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
        ec = asio::error_code(errno,
            asio::error::get_system_category());
# endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
        delete new_registration;
        return ec;
      }
    }
#endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)

    // Record the new registration in the set.
    new_registration->signal_number_ = signal_number;
    new_registration->queue_ = &impl.queue_;
    new_registration->next_in_set_ = next;
    *insertion_point = new_registration;

    // Insert registration into the registration table.
    new_registration->next_in_table_ = registrations_[signal_number];
    if (registrations_[signal_number])
      registrations_[signal_number]->prev_in_table_ = new_registration;
    registrations_[signal_number] = new_registration;

    ++state->registration_count_[signal_number];
  }

  ec = asio::error_code();
  return ec;
}