void select_reactor::run()

in demo_example/asio/asio/detail/impl/select_reactor.ipp [208:287]


void select_reactor::run(long usec, op_queue<operation>& ops)
{
  asio::detail::mutex::scoped_lock lock(mutex_);

#if defined(ASIO_HAS_IOCP)
  // Check if the thread is supposed to stop.
  if (stop_thread_)
    return;
#endif // defined(ASIO_HAS_IOCP)

  // Set up the descriptor sets.
  for (int i = 0; i < max_select_ops; ++i)
    fd_sets_[i].reset();
  fd_sets_[read_op].set(interrupter_.read_descriptor());
  socket_type max_fd = 0;
  bool have_work_to_do = !timer_queues_.all_empty();
  for (int i = 0; i < max_select_ops; ++i)
  {
    have_work_to_do = have_work_to_do || !op_queue_[i].empty();
    fd_sets_[i].set(op_queue_[i], ops);
    if (fd_sets_[i].max_descriptor() > max_fd)
      max_fd = fd_sets_[i].max_descriptor();
  }

#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
  // Connection operations on Windows use both except and write fd_sets.
  have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
  fd_sets_[write_op].set(op_queue_[connect_op], ops);
  if (fd_sets_[write_op].max_descriptor() > max_fd)
    max_fd = fd_sets_[write_op].max_descriptor();
  fd_sets_[except_op].set(op_queue_[connect_op], ops);
  if (fd_sets_[except_op].max_descriptor() > max_fd)
    max_fd = fd_sets_[except_op].max_descriptor();
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)

  // We can return immediately if there's no work to do and the reactor is
  // not supposed to block.
  if (!usec && !have_work_to_do)
    return;

  // Determine how long to block while waiting for events.
  timeval tv_buf = { 0, 0 };
  timeval* tv = usec ? get_timeout(usec, tv_buf) : &tv_buf;

  lock.unlock();

  // Block on the select call until descriptors become ready.
  asio::error_code ec;
  int retval = socket_ops::select(static_cast<int>(max_fd + 1),
      fd_sets_[read_op], fd_sets_[write_op], fd_sets_[except_op], tv, ec);

  // Reset the interrupter.
  if (retval > 0 && fd_sets_[read_op].is_set(interrupter_.read_descriptor()))
  {
    if (!interrupter_.reset())
    {
      lock.lock();
      interrupter_.recreate();
    }
    --retval;
  }

  lock.lock();

  // Dispatch all ready operations.
  if (retval > 0)
  {
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
    // Connection operations on Windows use both except and write fd_sets.
    fd_sets_[except_op].perform(op_queue_[connect_op], ops);
    fd_sets_[write_op].perform(op_queue_[connect_op], ops);
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)

    // Exception operations must be processed first to ensure that any
    // out-of-band data is read before normal data.
    for (int i = max_select_ops - 1; i >= 0; --i)
      fd_sets_[i].perform(op_queue_[i], ops);
  }
  timer_queues_.get_ready_timers(ops);
}