213 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| //
 | |
| // detail/reactor_op_queue.hpp
 | |
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| //
 | |
| // Copyright (c) 2003-2023 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 ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
 | |
| #define ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
 | |
| 
 | |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 | |
| # pragma once
 | |
| #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 | |
| 
 | |
| #include "asio/detail/config.hpp"
 | |
| #include "asio/detail/hash_map.hpp"
 | |
| #include "asio/detail/noncopyable.hpp"
 | |
| #include "asio/detail/op_queue.hpp"
 | |
| #include "asio/detail/reactor_op.hpp"
 | |
| #include "asio/error.hpp"
 | |
| 
 | |
| #include "asio/detail/push_options.hpp"
 | |
| 
 | |
| namespace asio {
 | |
| namespace detail {
 | |
| 
 | |
| template <typename Descriptor>
 | |
| class reactor_op_queue
 | |
|   : private noncopyable
 | |
| {
 | |
| public:
 | |
|   typedef Descriptor key_type;
 | |
| 
 | |
|   struct mapped_type : op_queue<reactor_op>
 | |
|   {
 | |
|     mapped_type() {}
 | |
|     mapped_type(const mapped_type&) {}
 | |
|     void operator=(const mapped_type&) {}
 | |
|   };
 | |
| 
 | |
|   typedef typename hash_map<key_type, mapped_type>::value_type value_type;
 | |
|   typedef typename hash_map<key_type, mapped_type>::iterator iterator;
 | |
| 
 | |
|   // Constructor.
 | |
|   reactor_op_queue()
 | |
|     : operations_()
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   // Obtain iterators to all registered descriptors.
 | |
|   iterator begin() { return operations_.begin(); }
 | |
|   iterator end() { return operations_.end(); }
 | |
| 
 | |
|   // 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)
 | |
|   {
 | |
|     std::pair<iterator, bool> entry =
 | |
|       operations_.insert(value_type(descriptor, mapped_type()));
 | |
|     entry.first->second.push(op);
 | |
|     return entry.second;
 | |
|   }
 | |
| 
 | |
|   // Cancel all operations associated with the descriptor identified by the
 | |
|   // supplied iterator. Any operations pending for the descriptor will be
 | |
|   // cancelled. 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(iterator i, op_queue<operation>& ops,
 | |
|       const asio::error_code& ec =
 | |
|         asio::error::operation_aborted)
 | |
|   {
 | |
|     if (i != operations_.end())
 | |
|     {
 | |
|       while (reactor_op* op = i->second.front())
 | |
|       {
 | |
|         op->ec_ = ec;
 | |
|         i->second.pop();
 | |
|         ops.push(op);
 | |
|       }
 | |
|       operations_.erase(i);
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // Cancel all operations associated with the descriptor. Any operations
 | |
|   // pending for the descriptor will be cancelled. 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 asio::error_code& ec =
 | |
|         asio::error::operation_aborted)
 | |
|   {
 | |
|     return this->cancel_operations(operations_.find(descriptor), ops, ec);
 | |
|   }
 | |
| 
 | |
|   // Cancel operations associated with the descriptor identified by the
 | |
|   // supplied iterator, and the specified cancellation key. Any operations
 | |
|   // pending for the descriptor with the key will be cancelled. 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_by_key(iterator i, op_queue<operation>& ops,
 | |
|       void* cancellation_key, const asio::error_code& ec =
 | |
|         asio::error::operation_aborted)
 | |
|   {
 | |
|     bool result = false;
 | |
|     if (i != operations_.end())
 | |
|     {
 | |
|       op_queue<reactor_op> other_ops;
 | |
|       while (reactor_op* op = i->second.front())
 | |
|       {
 | |
|         i->second.pop();
 | |
|         if (op->cancellation_key_ == cancellation_key)
 | |
|         {
 | |
|           op->ec_ = ec;
 | |
|           ops.push(op);
 | |
|           result = true;
 | |
|         }
 | |
|         else
 | |
|           other_ops.push(op);
 | |
|       }
 | |
|       i->second.push(other_ops);
 | |
|       if (i->second.empty())
 | |
|         operations_.erase(i);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   // Cancel all operations associated with the descriptor. Any operations
 | |
|   // pending for the descriptor will be cancelled. 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_by_key(Descriptor descriptor, op_queue<operation>& ops,
 | |
|       void* cancellation_key, const asio::error_code& ec =
 | |
|         asio::error::operation_aborted)
 | |
|   {
 | |
|     return this->cancel_operations_by_key(
 | |
|         operations_.find(descriptor), ops, cancellation_key, ec);
 | |
|   }
 | |
| 
 | |
|   // 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 identified by the
 | |
|   // supplied iterator. Returns true if there are still unfinished operations
 | |
|   // queued for the descriptor.
 | |
|   bool perform_operations(iterator i, op_queue<operation>& ops)
 | |
|   {
 | |
|     if (i != operations_.end())
 | |
|     {
 | |
|       while (reactor_op* op = i->second.front())
 | |
|       {
 | |
|         if (op->perform())
 | |
|         {
 | |
|           i->second.pop();
 | |
|           ops.push(op);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           return true;
 | |
|         }
 | |
|       }
 | |
|       operations_.erase(i);
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // 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)
 | |
|   {
 | |
|     return this->perform_operations(operations_.find(descriptor), ops);
 | |
|   }
 | |
| 
 | |
|   // Get all operations owned by the queue.
 | |
|   void get_all_operations(op_queue<operation>& ops)
 | |
|   {
 | |
|     iterator i = operations_.begin();
 | |
|     while (i != operations_.end())
 | |
|     {
 | |
|       iterator op_iter = i++;
 | |
|       ops.push(op_iter->second);
 | |
|       operations_.erase(op_iter);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   // The operations that are currently executing asynchronously.
 | |
|   hash_map<key_type, mapped_type> operations_;
 | |
| };
 | |
| 
 | |
| } // namespace detail
 | |
| } // namespace asio
 | |
| 
 | |
| #include "asio/detail/pop_options.hpp"
 | |
| 
 | |
| #endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
 |