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);
}