2 // prioritised_handlers.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2019 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
: public boost::asio::execution_context
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();
39 executor(handler_priority_queue
& q
, int p
)
40 : context_(q
), priority_(p
)
44 handler_priority_queue
& context() const
49 template <typename Function
, typename Allocator
>
50 void dispatch(const Function
& f
, const Allocator
&) const
52 context_
.add(priority_
, f
);
55 template <typename Function
, typename Allocator
>
56 void post(const Function
& f
, const Allocator
&) const
58 context_
.add(priority_
, f
);
61 template <typename Function
, typename Allocator
>
62 void defer(const Function
& f
, const Allocator
&) const
64 context_
.add(priority_
, f
);
67 void on_work_started() const {}
68 void on_work_finished() const {}
70 bool operator==(const executor
& other
) const
72 return &context_
== &other
.context_
&& priority_
== other
.priority_
;
75 bool operator!=(const executor
& other
) const
77 return !operator==(other
);
81 handler_priority_queue
& context_
;
85 template <typename Handler
>
86 boost::asio::executor_binder
<Handler
, executor
>
87 wrap(int priority
, Handler handler
)
89 return boost::asio::bind_executor(executor(*this, priority
), handler
);
96 queued_handler(int p
, boost::function
<void()> f
)
97 : priority_(p
), function_(f
)
106 friend bool operator<(const queued_handler
& a
,
107 const queued_handler
& b
)
109 return a
.priority_
< b
.priority_
;
114 boost::function
<void()> function_
;
117 std::priority_queue
<queued_handler
> handlers_
;
120 //----------------------------------------------------------------------
122 void high_priority_handler(const boost::system::error_code
& /*ec*/)
124 std::cout
<< "High priority handler\n";
127 void middle_priority_handler(const boost::system::error_code
& /*ec*/)
129 std::cout
<< "Middle priority handler\n";
132 void low_priority_handler()
134 std::cout
<< "Low priority handler\n";
139 boost::asio::io_context io_context
;
141 handler_priority_queue pri_queue
;
143 // Post a completion handler to be run immediately.
144 boost::asio::post(io_context
, pri_queue
.wrap(0, low_priority_handler
));
146 // Start an asynchronous accept that will complete immediately.
147 tcp::endpoint
endpoint(boost::asio::ip::address_v4::loopback(), 0);
148 tcp::acceptor
acceptor(io_context
, endpoint
);
149 tcp::socket
server_socket(io_context
);
150 acceptor
.async_accept(server_socket
,
151 pri_queue
.wrap(100, high_priority_handler
));
152 tcp::socket
client_socket(io_context
);
153 client_socket
.connect(acceptor
.local_endpoint());
155 // Set a deadline timer to expire immediately.
156 boost::asio::steady_timer
timer(io_context
);
157 timer
.expires_at(boost::asio::steady_timer::time_point::min());
158 timer
.async_wait(pri_queue
.wrap(42, middle_priority_handler
));
160 while (io_context
.run_one())
162 // The custom invocation hook adds the handlers to the priority queue
163 // rather than executing them from within the poll_one() call.
164 while (io_context
.poll_one())
167 pri_queue
.execute_all();