123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- //
- // detail/reactor_op_queue.hpp
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- #ifndef BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
- #define BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- # pragma once
- #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
- #include <boost/asio/detail/config.hpp>
- #include <boost/asio/detail/hash_map.hpp>
- #include <boost/asio/detail/noncopyable.hpp>
- #include <boost/asio/detail/op_queue.hpp>
- #include <boost/asio/detail/reactor_op.hpp>
- #include <boost/asio/error.hpp>
- #include <boost/asio/detail/push_options.hpp>
- namespace boost {
- namespace asio {
- namespace detail {
- template <typename Descriptor>
- class reactor_op_queue
- : private noncopyable
- {
- public:
- // Constructor.
- reactor_op_queue()
- : operations_()
- {
- }
- // Add a new operation to the queue. Returns true if this is the only
- // operation for the given descriptor, in which case the reactor's event
- // demultiplexing function call may need to be interrupted and restarted.
- bool enqueue_operation(Descriptor descriptor, reactor_op* op)
- {
- typedef typename operations_map::iterator iterator;
- typedef typename operations_map::value_type value_type;
- std::pair<iterator, bool> entry =
- operations_.insert(value_type(descriptor, operations()));
- entry.first->second.op_queue_.push(op);
- return entry.second;
- }
- // Cancel all operations associated with the descriptor. Any operations
- // pending for the descriptor will be notified that they have been cancelled
- // next time perform_cancellations is called. Returns true if any operations
- // were cancelled, in which case the reactor's event demultiplexing function
- // may need to be interrupted and restarted.
- bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops,
- const boost::system::error_code& ec =
- boost::asio::error::operation_aborted)
- {
- typename operations_map::iterator i = operations_.find(descriptor);
- if (i != operations_.end())
- {
- while (reactor_op* op = i->second.op_queue_.front())
- {
- op->ec_ = ec;
- i->second.op_queue_.pop();
- ops.push(op);
- }
- operations_.erase(i);
- return true;
- }
- return false;
- }
- // Whether there are no operations in the queue.
- bool empty() const
- {
- return operations_.empty();
- }
- // Determine whether there are any operations associated with the descriptor.
- bool has_operation(Descriptor descriptor) const
- {
- return operations_.find(descriptor) != operations_.end();
- }
- // Perform the operations corresponding to the descriptor. Returns true if
- // there are still unfinished operations queued for the descriptor.
- bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)
- {
- typename operations_map::iterator i = operations_.find(descriptor);
- if (i != operations_.end())
- {
- while (reactor_op* op = i->second.op_queue_.front())
- {
- if (op->perform())
- {
- i->second.op_queue_.pop();
- ops.push(op);
- }
- else
- {
- return true;
- }
- }
- operations_.erase(i);
- }
- return false;
- }
- // Fill a descriptor set with the descriptors corresponding to each active
- // operation. The op_queue is used only when descriptors fail to be added to
- // the descriptor set.
- template <typename Descriptor_Set>
- void get_descriptors(Descriptor_Set& descriptors, op_queue<operation>& ops)
- {
- typename operations_map::iterator i = operations_.begin();
- while (i != operations_.end())
- {
- Descriptor descriptor = i->first;
- ++i;
- if (!descriptors.set(descriptor))
- {
- boost::system::error_code ec(error::fd_set_failure);
- cancel_operations(descriptor, ops, ec);
- }
- }
- }
- // Perform the operations corresponding to the ready file descriptors
- // contained in the given descriptor set.
- template <typename Descriptor_Set>
- void perform_operations_for_descriptors(
- const Descriptor_Set& descriptors, op_queue<operation>& ops)
- {
- typename operations_map::iterator i = operations_.begin();
- while (i != operations_.end())
- {
- typename operations_map::iterator op_iter = i++;
- if (descriptors.is_set(op_iter->first))
- {
- while (reactor_op* op = op_iter->second.op_queue_.front())
- {
- if (op->perform())
- {
- op_iter->second.op_queue_.pop();
- ops.push(op);
- }
- else
- {
- break;
- }
- }
- if (op_iter->second.op_queue_.empty())
- operations_.erase(op_iter);
- }
- }
- }
- // Get all operations owned by the queue.
- void get_all_operations(op_queue<operation>& ops)
- {
- typename operations_map::iterator i = operations_.begin();
- while (i != operations_.end())
- {
- typename operations_map::iterator op_iter = i++;
- ops.push(op_iter->second.op_queue_);
- operations_.erase(op_iter);
- }
- }
- private:
- struct operations
- {
- operations() {}
- operations(const operations&) {}
- void operator=(const operations&) {}
- // The operations waiting on the desccriptor.
- op_queue<reactor_op> op_queue_;
- };
- // The type for a map of operations.
- typedef hash_map<Descriptor, operations> operations_map;
- // The operations that are currently executing asynchronously.
- operations_map operations_;
- };
- } // namespace detail
- } // namespace asio
- } // namespace boost
- #include <boost/asio/detail/pop_options.hpp>
- #endif // BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
|