diff options
Diffstat (limited to '3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp')
-rw-r--r-- | 3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp | 383 |
1 files changed, 64 insertions, 319 deletions
diff --git a/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp b/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp index 46f0c10..0dd5654 100644 --- a/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp +++ b/3rdParty/Boost/src/boost/asio/detail/reactor_op_queue.hpp @@ -17,14 +17,11 @@ #include <boost/asio/detail/push_options.hpp> -#include <boost/asio/detail/push_options.hpp> -#include <memory> -#include <boost/asio/detail/pop_options.hpp> - #include <boost/asio/error.hpp> -#include <boost/asio/detail/handler_alloc_helpers.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> namespace boost { namespace asio { @@ -37,39 +34,21 @@ class reactor_op_queue public: // Constructor. reactor_op_queue() - : operations_(), - cancelled_operations_(0), - complete_operations_(0) + : 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. - template <typename Operation> - bool enqueue_operation(Descriptor descriptor, Operation operation) + bool enqueue_operation(Descriptor descriptor, reactor_op* op) { - // Allocate and construct an object to wrap the handler. - typedef handler_alloc_traits<Operation, op<Operation> > alloc_traits; - raw_handler_ptr<alloc_traits> raw_ptr(operation); - handler_ptr<alloc_traits> ptr(raw_ptr, descriptor, operation); - - typedef typename operation_map::iterator iterator; - typedef typename operation_map::value_type value_type; + typedef typename operations_map::iterator iterator; + typedef typename operations_map::value_type value_type; std::pair<iterator, bool> entry = - operations_.insert(value_type(descriptor, ptr.get())); - if (entry.second) - { - ptr.release(); - return true; - } - - op_base* current_op = entry.first->second; - while (current_op->next_) - current_op = current_op->next_; - current_op->next_ = ptr.release(); - - return false; + 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 @@ -77,16 +56,19 @@ public: // 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) + bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops, + const boost::system::error_code& ec = + boost::asio::error::operation_aborted) { - typename operation_map::iterator i = operations_.find(descriptor); + typename operations_map::iterator i = operations_.find(descriptor); if (i != operations_.end()) { - op_base* last_op = i->second; - while (last_op->next_) - last_op = last_op->next_; - last_op->next_ = cancelled_operations_; - cancelled_operations_ = i->second; + 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; } @@ -106,79 +88,37 @@ public: return operations_.find(descriptor) != operations_.end(); } - // Perform the first operation corresponding to the descriptor. Returns true - // if there are more operations queued for the descriptor. - bool perform_operation(Descriptor descriptor, - const boost::system::error_code& result) + // 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 operation_map::iterator i = operations_.find(descriptor); + typename operations_map::iterator i = operations_.find(descriptor); if (i != operations_.end()) { - op_base* this_op = i->second; - i->second = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - bool done = this_op->perform(result); - if (done) + while (reactor_op* op = i->second.op_queue_.front()) { - // Operation has finished. - if (i->second) + if (op->perform()) { - return true; + i->second.op_queue_.pop(); + ops.push(op); } else { - operations_.erase(i); - return false; - } - } - else - { - // Operation wants to be called again. Leave it at the front of the - // queue for this descriptor, and remove from the completed list. - complete_operations_ = this_op->next_; - this_op->next_ = i->second; - i->second = this_op; - return true; - } - } - return false; - } - - // Perform all operations corresponding to the descriptor. - void perform_all_operations(Descriptor descriptor, - const boost::system::error_code& result) - { - typename operation_map::iterator i = operations_.find(descriptor); - if (i != operations_.end()) - { - while (i->second) - { - op_base* this_op = i->second; - i->second = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - bool done = this_op->perform(result); - if (!done) - { - // Operation has not finished yet, so leave at front of queue, and - // remove from the completed list. - complete_operations_ = this_op->next_; - this_op->next_ = i->second; - i->second = this_op; - return; + return true; } } operations_.erase(i); } + return false; } // Fill a descriptor set with the descriptors corresponding to each active - // operation. + // 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) + void get_descriptors(Descriptor_Set& descriptors, op_queue<operation>& ops) { - typename operation_map::iterator i = operations_.begin(); + typename operations_map::iterator i = operations_.begin(); while (i != operations_.end()) { Descriptor descriptor = i->first; @@ -186,7 +126,7 @@ public: if (!descriptors.set(descriptor)) { boost::system::error_code ec(error::fd_set_failure); - perform_all_operations(descriptor, ec); + cancel_operations(descriptor, ops, ec); } } } @@ -194,257 +134,62 @@ public: // 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, - const boost::system::error_code& result) + void perform_operations_for_descriptors( + const Descriptor_Set& descriptors, op_queue<operation>& ops) { - typename operation_map::iterator i = operations_.begin(); + typename operations_map::iterator i = operations_.begin(); while (i != operations_.end()) { - typename operation_map::iterator op_iter = i++; + typename operations_map::iterator op_iter = i++; if (descriptors.is_set(op_iter->first)) { - op_base* this_op = op_iter->second; - op_iter->second = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - bool done = this_op->perform(result); - if (done) - { - if (!op_iter->second) - operations_.erase(op_iter); - } - else + while (reactor_op* op = op_iter->second.op_queue_.front()) { - // Operation has not finished yet, so leave at front of queue, and - // remove from the completed list. - complete_operations_ = this_op->next_; - this_op->next_ = op_iter->second; - op_iter->second = this_op; + if (op->perform()) + { + op_iter->second.op_queue_.pop(); + ops.push(op); + } + else + { + break; + } } - } - } - } - - // Perform any pending cancels for operations. - void perform_cancellations() - { - while (cancelled_operations_) - { - op_base* this_op = cancelled_operations_; - cancelled_operations_ = this_op->next_; - this_op->next_ = complete_operations_; - complete_operations_ = this_op; - this_op->perform(boost::asio::error::operation_aborted); - } - } - // Complete all operations that are waiting to be completed. - void complete_operations() - { - while (complete_operations_) - { - op_base* next_op = complete_operations_->next_; - complete_operations_->next_ = 0; - complete_operations_->complete(); - complete_operations_ = next_op; + if (op_iter->second.op_queue_.empty()) + operations_.erase(op_iter); + } } } - // Destroy all operations owned by the queue. - void destroy_operations() + // Get all operations owned by the queue. + void get_all_operations(op_queue<operation>& ops) { - while (cancelled_operations_) - { - op_base* next_op = cancelled_operations_->next_; - cancelled_operations_->next_ = 0; - cancelled_operations_->destroy(); - cancelled_operations_ = next_op; - } - - while (complete_operations_) - { - op_base* next_op = complete_operations_->next_; - complete_operations_->next_ = 0; - complete_operations_->destroy(); - complete_operations_ = next_op; - } - - typename operation_map::iterator i = operations_.begin(); + typename operations_map::iterator i = operations_.begin(); while (i != operations_.end()) { - typename operation_map::iterator op_iter = i++; - op_base* curr_op = op_iter->second; + typename operations_map::iterator op_iter = i++; + ops.push(op_iter->second.op_queue_); operations_.erase(op_iter); - while (curr_op) - { - op_base* next_op = curr_op->next_; - curr_op->next_ = 0; - curr_op->destroy(); - curr_op = next_op; - } } } private: - // Base class for reactor operations. A function pointer is used instead of - // virtual functions to avoid the associated overhead. - class op_base - { - public: - // Get the descriptor associated with the operation. - Descriptor descriptor() const - { - return descriptor_; - } - - // Perform the operation. - bool perform(const boost::system::error_code& result) - { - result_ = result; - return perform_func_(this, result_, bytes_transferred_); - } - - // Destroy the operation and post the handler. - void complete() - { - complete_func_(this, result_, bytes_transferred_); - } - - // Destroy the operation. - void destroy() - { - destroy_func_(this); - } - - protected: - typedef bool (*perform_func_type)(op_base*, - boost::system::error_code&, std::size_t&); - typedef void (*complete_func_type)(op_base*, - const boost::system::error_code&, std::size_t); - typedef void (*destroy_func_type)(op_base*); - - // Construct an operation for the given descriptor. - op_base(perform_func_type perform_func, complete_func_type complete_func, - destroy_func_type destroy_func, Descriptor descriptor) - : perform_func_(perform_func), - complete_func_(complete_func), - destroy_func_(destroy_func), - descriptor_(descriptor), - result_(), - bytes_transferred_(0), - next_(0) - { - } - - // Prevent deletion through this type. - ~op_base() - { - } - - private: - friend class reactor_op_queue<Descriptor>; - - // The function to be called to perform the operation. - perform_func_type perform_func_; - - // The function to be called to delete the operation and post the handler. - complete_func_type complete_func_; - - // The function to be called to delete the operation. - destroy_func_type destroy_func_; - - // The descriptor associated with the operation. - Descriptor descriptor_; - - // The result of the operation. - boost::system::error_code result_; - - // The number of bytes transferred in the operation. - std::size_t bytes_transferred_; - - // The next operation for the same file descriptor. - op_base* next_; - }; - - // Adaptor class template for operations. - template <typename Operation> - class op - : public op_base + struct operations { - public: - // Constructor. - op(Descriptor descriptor, Operation operation) - : op_base(&op<Operation>::do_perform, &op<Operation>::do_complete, - &op<Operation>::do_destroy, descriptor), - operation_(operation) - { - } - - // Perform the operation. - static bool do_perform(op_base* base, - boost::system::error_code& result, std::size_t& bytes_transferred) - { - return static_cast<op<Operation>*>(base)->operation_.perform( - result, bytes_transferred); - } - - // Destroy the operation and post the handler. - static void do_complete(op_base* base, - const boost::system::error_code& result, std::size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef op<Operation> this_type; - this_type* this_op(static_cast<this_type*>(base)); - typedef handler_alloc_traits<Operation, this_type> alloc_traits; - handler_ptr<alloc_traits> ptr(this_op->operation_, this_op); - - // Make a copy of the error_code and the operation so that the memory can - // be deallocated before the upcall is made. - boost::system::error_code ec(result); - Operation operation(this_op->operation_); - - // Free the memory associated with the operation. - ptr.reset(); - - // Make the upcall. - operation.complete(ec, bytes_transferred); - } - - // Destroy the operation. - static void do_destroy(op_base* base) - { - // Take ownership of the operation object. - typedef op<Operation> this_type; - this_type* this_op(static_cast<this_type*>(base)); - typedef handler_alloc_traits<Operation, this_type> alloc_traits; - handler_ptr<alloc_traits> ptr(this_op->operation_, this_op); - - // A sub-object of the operation may be the true owner of the memory - // associated with the operation. Consequently, a local copy of the - // operation is required to ensure that any owning sub-object remains - // valid until after we have deallocated the memory here. - Operation operation(this_op->operation_); - (void)operation; - - // Free the memory associated with the operation. - ptr.reset(); - } + operations() {} + operations(const operations&) {} + void operator=(const operations&) {} - private: - Operation operation_; + // The operations waiting on the desccriptor. + op_queue<reactor_op> op_queue_; }; // The type for a map of operations. - typedef hash_map<Descriptor, op_base*> operation_map; + typedef hash_map<Descriptor, operations> operations_map; // The operations that are currently executing asynchronously. - operation_map operations_; - - // The list of operations that have been cancelled. - op_base* cancelled_operations_; - - // The list of operations waiting to be completed. - op_base* complete_operations_; + operations_map operations_; }; } // namespace detail |