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