]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp03/invocation/prioritised_handlers.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / asio / example / cpp03 / invocation / prioritised_handlers.cpp
1 //
2 // prioritised_handlers.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2017 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 #include <boost/asio.hpp>
12 #include <boost/function.hpp>
13 #include <iostream>
14 #include <queue>
15
16 using boost::asio::ip::tcp;
17
18 class handler_priority_queue : boost::asio::execution_context
19 {
20 public:
21 void add(int priority, boost::function<void()> function)
22 {
23 handlers_.push(queued_handler(priority, function));
24 }
25
26 void execute_all()
27 {
28 while (!handlers_.empty())
29 {
30 queued_handler handler = handlers_.top();
31 handler.execute();
32 handlers_.pop();
33 }
34 }
35
36 class executor
37 {
38 public:
39 executor(handler_priority_queue& q, int p)
40 : context_(q), priority_(p)
41 {
42 }
43
44 handler_priority_queue& context() const
45 {
46 return context_;
47 }
48
49 template <typename Function, typename Allocator>
50 void dispatch(const Function& f, const Allocator&) const
51 {
52 context_.add(priority_, f);
53 }
54
55 template <typename Function, typename Allocator>
56 void post(const Function& f, const Allocator&) const
57 {
58 context_.add(priority_, f);
59 }
60
61 template <typename Function, typename Allocator>
62 void defer(const Function& f, const Allocator&) const
63 {
64 context_.add(priority_, f);
65 }
66
67 void on_work_started() const {}
68 void on_work_finished() const {}
69
70 bool operator==(const executor& other) const
71 {
72 return &context_ == &other.context_ && priority_ == other.priority_;
73 }
74
75 bool operator!=(const executor& other) const
76 {
77 return !operator==(other);
78 }
79
80 private:
81 handler_priority_queue& context_;
82 int priority_;
83 };
84
85 template <typename Handler>
86 boost::asio::executor_binder<Handler, executor>
87 wrap(int priority, Handler handler)
88 {
89 return boost::asio::bind_executor(executor(*this, priority), handler);
90 }
91
92 private:
93 class queued_handler
94 {
95 public:
96 queued_handler(int p, boost::function<void()> f)
97 : priority_(p), function_(f)
98 {
99 }
100
101 void execute()
102 {
103 function_();
104 }
105
106 friend bool operator<(const queued_handler& a,
107 const queued_handler& b)
108 {
109 return a.priority_ < b.priority_;
110 }
111
112 private:
113 int priority_;
114 boost::function<void()> function_;
115 };
116
117 std::priority_queue<queued_handler> handlers_;
118 };
119
120 //----------------------------------------------------------------------
121
122 void high_priority_handler(const boost::system::error_code& /*ec*/)
123 {
124 std::cout << "High priority handler\n";
125 }
126
127 void middle_priority_handler(const boost::system::error_code& /*ec*/)
128 {
129 std::cout << "Middle priority handler\n";
130 }
131
132 void low_priority_handler()
133 {
134 std::cout << "Low priority handler\n";
135 }
136
137 int main()
138 {
139 boost::asio::io_context io_context;
140
141 handler_priority_queue pri_queue;
142
143 // Post a completion handler to be run immediately.
144 boost::asio::post(io_context, pri_queue.wrap(0, low_priority_handler));
145
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());
154
155 // Set a deadline timer to expire immediately.
156 boost::asio::deadline_timer timer(io_context);
157 timer.expires_at(boost::posix_time::neg_infin);
158 timer.async_wait(pri_queue.wrap(42, middle_priority_handler));
159
160 while (io_context.run_one())
161 {
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())
165 ;
166
167 pri_queue.execute_all();
168 }
169
170 return 0;
171 }