Home | History | Annotate | Download | only in detail
      1 //
      2 // detail/reactor_op_queue.hpp
      3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      4 //
      5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
      6 //
      7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
      8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      9 //
     10 
     11 #ifndef ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
     12 #define ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
     13 
     14 
     15 #include "asio/detail/config.hpp"
     16 #include "asio/detail/hash_map.hpp"
     17 #include "asio/detail/noncopyable.hpp"
     18 #include "asio/detail/op_queue.hpp"
     19 #include "asio/detail/reactor_op.hpp"
     20 #include "asio/error.hpp"
     21 
     22 #include "asio/detail/push_options.hpp"
     23 
     24 namespace asio {
     25 namespace detail {
     26 
     27 template <typename Descriptor>
     28 class reactor_op_queue
     29   : private noncopyable
     30 {
     31 public:
     32   typedef Descriptor key_type;
     33 
     34   struct mapped_type : op_queue<reactor_op>
     35   {
     36     mapped_type() {}
     37     mapped_type(const mapped_type&) {}
     38     void operator=(const mapped_type&) {}
     39   };
     40 
     41   typedef typename hash_map<key_type, mapped_type>::value_type value_type;
     42   typedef typename hash_map<key_type, mapped_type>::iterator iterator;
     43 
     44   // Constructor.
     45   reactor_op_queue()
     46     : operations_()
     47   {
     48   }
     49 
     50   // Obtain iterators to all registered descriptors.
     51   iterator begin() { return operations_.begin(); }
     52   iterator end() { return operations_.end(); }
     53 
     54   // Add a new operation to the queue. Returns true if this is the only
     55   // operation for the given descriptor, in which case the reactor's event
     56   // demultiplexing function call may need to be interrupted and restarted.
     57   bool enqueue_operation(Descriptor descriptor, reactor_op* op)
     58   {
     59     std::pair<iterator, bool> entry =
     60       operations_.insert(value_type(descriptor, mapped_type()));
     61     entry.first->second.push(op);
     62     return entry.second;
     63   }
     64 
     65   // Cancel all operations associated with the descriptor identified by the
     66   // supplied iterator. Any operations pending for the descriptor will be
     67   // cancelled. Returns true if any operations were cancelled, in which case
     68   // the reactor's event demultiplexing function may need to be interrupted and
     69   // restarted.
     70   bool cancel_operations(iterator i, op_queue<operation>& ops,
     71       const asio::error_code& ec =
     72         asio::error::operation_aborted)
     73   {
     74     if (i != operations_.end())
     75     {
     76       while (reactor_op* op = i->second.front())
     77       {
     78         op->ec_ = ec;
     79         i->second.pop();
     80         ops.push(op);
     81       }
     82       operations_.erase(i);
     83       return true;
     84     }
     85 
     86     return false;
     87   }
     88 
     89   // Cancel all operations associated with the descriptor. Any operations
     90   // pending for the descriptor will be cancelled. Returns true if any
     91   // operations were cancelled, in which case the reactor's event
     92   // demultiplexing function may need to be interrupted and restarted.
     93   bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops,
     94       const asio::error_code& ec =
     95         asio::error::operation_aborted)
     96   {
     97     return this->cancel_operations(operations_.find(descriptor), ops, ec);
     98   }
     99 
    100   // Whether there are no operations in the queue.
    101   bool empty() const
    102   {
    103     return operations_.empty();
    104   }
    105 
    106   // Determine whether there are any operations associated with the descriptor.
    107   bool has_operation(Descriptor descriptor) const
    108   {
    109     return operations_.find(descriptor) != operations_.end();
    110   }
    111 
    112   // Perform the operations corresponding to the descriptor identified by the
    113   // supplied iterator. Returns true if there are still unfinished operations
    114   // queued for the descriptor.
    115   bool perform_operations(iterator i, op_queue<operation>& ops)
    116   {
    117     if (i != operations_.end())
    118     {
    119       while (reactor_op* op = i->second.front())
    120       {
    121         if (op->perform())
    122         {
    123           i->second.pop();
    124           ops.push(op);
    125         }
    126         else
    127         {
    128           return true;
    129         }
    130       }
    131       operations_.erase(i);
    132     }
    133     return false;
    134   }
    135 
    136   // Perform the operations corresponding to the descriptor. Returns true if
    137   // there are still unfinished operations queued for the descriptor.
    138   bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)
    139   {
    140     return this->perform_operations(operations_.find(descriptor), ops);
    141   }
    142 
    143   // Get all operations owned by the queue.
    144   void get_all_operations(op_queue<operation>& ops)
    145   {
    146     iterator i = operations_.begin();
    147     while (i != operations_.end())
    148     {
    149       iterator op_iter = i++;
    150       ops.push(op_iter->second);
    151       operations_.erase(op_iter);
    152     }
    153   }
    154 
    155 private:
    156   // The operations that are currently executing asynchronously.
    157   hash_map<key_type, mapped_type> operations_;
    158 };
    159 
    160 } // namespace detail
    161 } // namespace asio
    162 
    163 #include "asio/detail/pop_options.hpp"
    164 
    165 #endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
    166