2 // prioritised_handlers.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #include <boost/asio.hpp>
12 #include <boost/function.hpp>
16 using boost::asio::ip::tcp
;
18 class handler_priority_queue
21 void add(int priority
, boost::function
<void()> function
)
23 handlers_
.push(queued_handler(priority
, function
));
28 while (!handlers_
.empty())
30 queued_handler handler
= handlers_
.top();
36 // A generic wrapper class for handlers to allow the invocation to be hooked.
37 template <typename Handler
>
41 wrapped_handler(handler_priority_queue
& q
, int p
, Handler h
)
42 : queue_(q
), priority_(p
), handler_(h
)
51 template <typename Arg1
>
52 void operator()(Arg1 arg1
)
57 template <typename Arg1
, typename Arg2
>
58 void operator()(Arg1 arg1
, Arg2 arg2
)
64 handler_priority_queue
& queue_
;
69 template <typename Handler
>
70 wrapped_handler
<Handler
> wrap(int priority
, Handler handler
)
72 return wrapped_handler
<Handler
>(*this, priority
, handler
);
79 queued_handler(int p
, boost::function
<void()> f
)
80 : priority_(p
), function_(f
)
89 friend bool operator<(const queued_handler
& a
,
90 const queued_handler
& b
)
92 return a
.priority_
< b
.priority_
;
97 boost::function
<void()> function_
;
100 std::priority_queue
<queued_handler
> handlers_
;
103 // Custom invocation hook for wrapped handlers.
104 template <typename Function
, typename Handler
>
105 void asio_handler_invoke(Function f
,
106 handler_priority_queue::wrapped_handler
<Handler
>* h
)
108 h
->queue_
.add(h
->priority_
, f
);
111 //----------------------------------------------------------------------
113 void high_priority_handler(const boost::system::error_code
& /*ec*/)
115 std::cout
<< "High priority handler\n";
118 void middle_priority_handler(const boost::system::error_code
& /*ec*/)
120 std::cout
<< "Middle priority handler\n";
123 void low_priority_handler()
125 std::cout
<< "Low priority handler\n";
130 boost::asio::io_service io_service
;
132 handler_priority_queue pri_queue
;
134 // Post a completion handler to be run immediately.
135 io_service
.post(pri_queue
.wrap(0, low_priority_handler
));
137 // Start an asynchronous accept that will complete immediately.
138 tcp::endpoint
endpoint(boost::asio::ip::address_v4::loopback(), 0);
139 tcp::acceptor
acceptor(io_service
, endpoint
);
140 tcp::socket
server_socket(io_service
);
141 acceptor
.async_accept(server_socket
,
142 pri_queue
.wrap(100, high_priority_handler
));
143 tcp::socket
client_socket(io_service
);
144 client_socket
.connect(acceptor
.local_endpoint());
146 // Set a deadline timer to expire immediately.
147 boost::asio::deadline_timer
timer(io_service
);
148 timer
.expires_at(boost::posix_time::neg_infin
);
149 timer
.async_wait(pri_queue
.wrap(42, middle_priority_handler
));
151 while (io_service
.run_one())
153 // The custom invocation hook adds the handlers to the priority queue
154 // rather than executing them from within the poll_one() call.
155 while (io_service
.poll_one())
158 pri_queue
.execute_all();