src/​examples/​cpp03/​invocation/​prioritised_handlers.​cppsrc/​examples/​cpp11/​invocation/​prioritised_handlers.​cpp
⋮⋮
1 /​/​1 /​/​
2 /​/​·​prioritised_handlers.​cpp2 /​/​·​prioritised_handlers.​cpp
3 /​/​·​~~~~~~~~~~~~~~~~~~~~~​~~~3 /​/​·​~~~~~~~~~~~~~~~~~~~~~​~~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2020·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2020·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​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)​8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​
9 /​/​9 /​/​
10 10
11 #include·​"asio.​hpp"11 #include·​"asio.​hpp"
12 #include·​<boost/​function.​hpp>
13 #include·​<iostream>12 #include·​<iostream>
13 #include·​<memory>
14 #include·​<queue>14 #include·​<queue>
15 15
16 using·​asio:​:​ip:​:​tcp;​16 using·​asio:​:​ip:​:​tcp;​
17 17
18 class·​handler_priority_queu​e·​:​·​public·​asio:​:​execution_context18 class·​handler_priority_queu​e·​:​·​public·​asio:​:​execution_context
19 {19 {
20 public:​20 public:​
21 ·​·​void·​add(int·​priority,​·​boost:​:​function<void()​>·​function)​21 ·​·​template·​<typename·​Function>
22 ·​·​void·​add(int·​priority,​·​Function·​function)​
22 ·​·​{23 ·​·​{
23 ·​·​·​·​handlers_.​push(queued_handler(p​riority,​·​function)​)​;​24 ·​·​·​·​std:​:​unique_ptr<queued_han​dler_base>·​handler(
25 ·​·​·​·​·​·​·​·​new·​queued_handler<Functi​on>(
26 ·​·​·​·​·​·​·​·​·​·​priority,​·​std:​:​move(function)​)​)​;​
27
28 ·​·​·​·​handlers_.​push(std:​:​move(handler)​)​;​
24 ·​·​}29 ·​·​}
25 30
26 ·​·​void·​execute_all()​31 ·​·​void·​execute_all()​
27 ·​·​{32 ·​·​{
28 ·​·​·​·​while·​(!handlers_.​empty()​)​33 ·​·​·​·​while·​(!handlers_.​empty()​)​
29 ·​·​·​·​{34 ·​·​·​·​{
30 ·​·​·​·​·​·​queued_handler·​handler·​=·​handlers_.​top()​;​35 ·​·​·​·​·​·​handlers_.​top()​-​>execute()​;​
31 ·​·​·​·​·​·​handler.​execute()​;​
32 ·​·​·​·​·​·​handlers_.​pop()​;​36 ·​·​·​·​·​·​handlers_.​pop()​;​
33 ·​·​·​·​}37 ·​·​·​·​}
34 ·​·​}38 ·​·​}
35 39
36 ·​·​class·​executor40 ·​·​class·​executor
37 ·​·​{41 ·​·​{
38 ·​·​public:​42 ·​·​public:​
39 ·​·​·​·​executor(handler_prio​rity_queue&·​q,​·​int·​p)​43 ·​·​·​·​executor(handler_prio​rity_queue&·​q,​·​int·​p)​
40 ·​·​·​·​·​·​:​·​context_(q)​,​·​priority_(p)​44 ·​·​·​·​·​·​:​·​context_(q)​,​·​priority_(p)​
41 ·​·​·​·​{45 ·​·​·​·​{
42 ·​·​·​·​}46 ·​·​·​·​}
43 47
44 ·​·​·​·​handler_priority_queu​e&·​context()​·​const48 ·​·​·​·​handler_priority_queu​e&·​context()​·​const·​noexcept
45 ·​·​·​·​{49 ·​·​·​·​{
46 ·​·​·​·​·​·​return·​context_;​50 ·​·​·​·​·​·​return·​context_;​
47 ·​·​·​·​}51 ·​·​·​·​}
48 52
49 ·​·​·​·​template·​<typename·​Function,​·​typename·​Allocator>53 ·​·​·​·​template·​<typename·​Function,​·​typename·​Allocator>
50 ·​·​·​·​void·​dispatch(const·​Function&·​f,​·​const·​Allocator&)​·​const54 ·​·​·​·​void·​dispatch(Function·​f,​·​const·​Allocator&)​·​const
51 ·​·​·​·​{55 ·​·​·​·​{
52 ·​·​·​·​·​·​context_.​add(priority_,​·​f)​;​56 ·​·​·​·​·​·​context_.​add(priority_,​·​std:​:​move(f)​)​;​
53 ·​·​·​·​}57 ·​·​·​·​}
54 58
55 ·​·​·​·​template·​<typename·​Function,​·​typename·​Allocator>59 ·​·​·​·​template·​<typename·​Function,​·​typename·​Allocator>
56 ·​·​·​·​void·​post(const·​Function&·​f,​·​const·​Allocator&)​·​const60 ·​·​·​·​void·​post(Function·​f,​·​const·​Allocator&)​·​const
57 ·​·​·​·​{61 ·​·​·​·​{
58 ·​·​·​·​·​·​context_.​add(priority_,​·​f)​;​62 ·​·​·​·​·​·​context_.​add(priority_,​·​std:​:​move(f)​)​;​
59 ·​·​·​·​}63 ·​·​·​·​}
60 64
61 ·​·​·​·​template·​<typename·​Function,​·​typename·​Allocator>65 ·​·​·​·​template·​<typename·​Function,​·​typename·​Allocator>
62 ·​·​·​·​void·​defer(const·​Function&·​f,​·​const·​Allocator&)​·​const66 ·​·​·​·​void·​defer(Function·​f,​·​const·​Allocator&)​·​const
63 ·​·​·​·​{67 ·​·​·​·​{
64 ·​·​·​·​·​·​context_.​add(priority_,​·​f)​;​68 ·​·​·​·​·​·​context_.​add(priority_,​·​std:​:​move(f)​)​;​
65 ·​·​·​·​}69 ·​·​·​·​}
66 70
67 ·​·​·​·​void·​on_work_started()​·​const·​{}71 ·​·​·​·​void·​on_work_started()​·​const·​noexcept·​{}
68 ·​·​·​·​void·​on_work_finished()​·​const·​{}72 ·​·​·​·​void·​on_work_finished()​·​const·​noexcept·​{}
69 73
70 ·​·​·​·​bool·​operator==(const·​executor&·​other)​·​const74 ·​·​·​·​bool·​operator==(const·​executor&·​other)​·​const·​noexcept
71 ·​·​·​·​{75 ·​·​·​·​{
72 ·​·​·​·​·​·​return·​&context_·​==·​&other.​context_·​&&·​priority_·​==·​other.​priority_;​76 ·​·​·​·​·​·​return·​&context_·​==·​&other.​context_·​&&·​priority_·​==·​other.​priority_;​
73 ·​·​·​·​}77 ·​·​·​·​}
74 78
75 ·​·​·​·​bool·​operator!=(const·​executor&·​other)​·​const79 ·​·​·​·​bool·​operator!=(const·​executor&·​other)​·​const·​noexcept
76 ·​·​·​·​{80 ·​·​·​·​{
77 ·​·​·​·​·​·​return·​!operator==(other)​;​81 ·​·​·​·​·​·​return·​!operator==(other)​;​
78 ·​·​·​·​}82 ·​·​·​·​}
79 83
80 ·​·​private:​84 ·​·​private:​
81 ·​·​·​·​handler_priority_queu​e&·​context_;​85 ·​·​·​·​handler_priority_queu​e&·​context_;​
82 ·​·​·​·​int·​priority_;​86 ·​·​·​·​int·​priority_;​
83 ·​·​};​87 ·​·​};​
84 88
85 ·​·​template·​<typename·​Handler>89 ·​·​template·​<typename·​Handler>
86 ·​·​asio:​:​executor_binder<Handl​er,​·​executor>90 ·​·​asio:​:​executor_binder<Handl​er,​·​executor>
87 ·​·​wrap(int·​priority,​·​Handler·​handler)​91 ·​·​wrap(int·​priority,​·​Handler·​handler)​
88 ·​·​{92 ·​·​{
89 ·​·​·​·​return·​asio:​:​bind_executor(executo​r(*this,​·​priority)​,​·​handler)​;​93 ·​·​·​·​return·​asio:​:​bind_executor(
94 ·​·​·​·​·​·​·​·​executor(*this,​·​priority)​,​·​std:​:​move(handler)​)​;​
90 ·​·​}95 ·​·​}
91 96
92 private:​97 private:​
93 ·​·​class·​queued_handler98 ·​·​class·​queued_handler_base
94 ·​·​{99 ·​·​{
95 ·​·​public:​100 ·​·​public:​
96 ·​·​·​·​queued_handler(int·​p,​·​boost:​:​function<void()​>·​f)​101 ·​·​·​·​queued_handler_base(i​nt·​p)​
97 ·​·​·​·​·​·​:​·​priority_(p)​,​·​function_(f)​102 ·​·​·​·​·​·​:​·​priority_(p)​
98 ·​·​·​·​{103 ·​·​·​·​{
99 ·​·​·​·​}104 ·​·​·​·​}
100 105
101 ·​·​·​·​void·​execute()​106 ·​·​·​·​virtual·​~queued_handler_base(​)​
102 ·​·​·​·​{107 ·​·​·​·​{
103 ·​·​·​·​·​·​function_()​;​
104 ·​·​·​·​}108 ·​·​·​·​}
105 109
106 ·​·​·​·​friend·​bool·​operator<(const·​queued_handler&·​a,​110 ·​·​·​·​virtual·​void·​execute()​·​=·​0;​
107 ·​·​·​·​·​·​·​·​const·​queued_handler&·​b)​111
112 ·​·​·​·​friend·​bool·​operator<(const·​std:​:​unique_ptr<queued_han​dler_base>&·​a,​
113 ·​·​·​·​·​·​·​·​const·​std:​:​unique_ptr<queued_han​dler_base>&·​b)​·​noexcept
108 ·​·​·​·​{114 ·​·​·​·​{
109 ·​·​·​·​·​·​return·​a.​priority_·​<·​b.​priority_;​115 ·​·​·​·​·​·​return·​a-​>priority_·​<·​b-​>priority_;​
110 ·​·​·​·​}116 ·​·​·​·​}
111 117
112 ·​·​private:​118 ·​·​private:​
113 ·​·​·​·​int·​priority_;​119 ·​·​·​·​int·​priority_;​
114 ·​·​·​·​boost:​:​function<void()​>·​function_;​
115 ·​·​};​120 ·​·​};​
116 121
117 ·​·​std:​:​priority_queue<queued​_handler>·​handlers_;​122 ·​·​template·​<typename·​Function>
123 ·​·​class·​queued_handler·​:​·​public·​queued_handler_base
124 ·​·​{
125 ·​·​public:​
126 ·​·​·​·​queued_handler(int·​p,​·​Function·​f)​
127 ·​·​·​·​·​·​:​·​queued_handler_base(p​)​,​·​function_(std:​:​move(f)​)​
128 ·​·​·​·​{
129 ·​·​·​·​}
130
131 ·​·​·​·​void·​execute()​·​override
132 ·​·​·​·​{
133 ·​·​·​·​·​·​function_()​;​
134 ·​·​·​·​}
135
136 ·​·​private:​
137 ·​·​·​·​Function·​function_;​
138 ·​·​};​
139
140 ·​·​std:​:​priority_queue<std:​:​unique_ptr<queued_han​dler_base>>·​handlers_;​
118 };​141 };​
119 142
120 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​143 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​
121 144
122 void·​high_priority_handler​(const·​asio:​:​error_code&·​/​*ec*/​)​145 void·​high_priority_handler​(const·​asio:​:​error_code&·​/​*ec*/​,​
146 ·​·​·​·​tcp:​:​socket·​/​*socket*/​)​
123 {147 {
124 ·​·​std:​:​cout·​<<·​"High·​priority·​handler\n";​148 ·​·​std:​:​cout·​<<·​"High·​priority·​handler\n";​
125 }149 }
126 150
127 void·​middle_priority_handl​er(const·​asio:​:​error_code&·​/​*ec*/​)​151 void·​middle_priority_handl​er(const·​asio:​:​error_code&·​/​*ec*/​)​
128 {152 {
129 ·​·​std:​:​cout·​<<·​"Middle·​priority·​handler\n";​153 ·​·​std:​:​cout·​<<·​"Middle·​priority·​handler\n";​
130 }154 }
131 155
132 void·​low_priority_handler(​)​156 struct·​low_priority_handler
133 {157 {
134 ·​·​std:​:​cout·​<<·​"Low·​priority·​handler\n";​158 ·​·​/​/​·​Make·​the·​handler·​a·​move-​only·​type.​
135 }159 ·​·​low_priority_handler(​)​·​=·​default;​
160 ·​·​low_priority_handler(​const·​low_priority_handler&​)​·​=·​delete;​
161 ·​·​low_priority_handler(​low_priority_handler&​&)​·​=·​default;​
162
163 ·​·​void·​operator()​()​
164 ·​·​{
165 ·​·​·​·​std:​:​cout·​<<·​"Low·​priority·​handler\n";​
166 ·​·​}
167 };​
136 168
137 int·​main()​169 int·​main()​
138 {170 {
139 ·​·​asio:​:​io_context·​io_context;​171 ·​·​asio:​:​io_context·​io_context;​
140 172
141 ·​·​handler_priority_queu​e·​pri_queue;​173 ·​·​handler_priority_queu​e·​pri_queue;​
142 174
143 ·​·​/​/​·​Post·​a·​completion·​handler·​to·​be·​run·​immediately.​175 ·​·​/​/​·​Post·​a·​completion·​handler·​to·​be·​run·​immediately.​
144 ·​·​asio:​:​post(io_context,​·​pri_queue.​wrap(0,​·​low_priority_handler)​)​;​176 ·​·​asio:​:​post(io_context,​·​pri_queue.​wrap(0,​·​low_priority_handler(​)​)​)​;​
145 177
146 ·​·​/​/​·​Start·​an·​asynchronous·​accept·​that·​will·​complete·​immediately.​178 ·​·​/​/​·​Start·​an·​asynchronous·​accept·​that·​will·​complete·​immediately.​
147 ·​·​tcp:​:​endpoint·​endpoint(asio:​:​ip:​:​address_v4:​:​loopback()​,​·​0)​;​179 ·​·​tcp:​:​endpoint·​endpoint(asio:​:​ip:​:​address_v4:​:​loopback()​,​·​0)​;​
148 ·​·​tcp:​:​acceptor·​acceptor(io_context,​·​endpoint)​;​180 ·​·​tcp:​:​acceptor·​acceptor(io_context,​·​endpoint)​;​
149 ·​·​tcp:​:​socket·​server_socket(io_cont​ext)​;​181 ·​·​tcp:​:​socket·​server_socket(io_cont​ext)​;​
150 ·​·​acceptor.​async_accept(server_s​ocket,​182 ·​·​acceptor.​async_accept(pri_queu​e.​wrap(100,​·​high_priority_handler​)​)​;​
151 ·​·​·​·​·​·​pri_queue.​wrap(100,​·​high_priority_handler​)​)​;​
152 ·​·​tcp:​:​socket·​client_socket(io_cont​ext)​;​183 ·​·​tcp:​:​socket·​client_socket(io_cont​ext)​;​
153 ·​·​client_socket.​connect(acceptor.​local_endpoint()​)​;​184 ·​·​client_socket.​connect(acceptor.​local_endpoint()​)​;​
154 185
155 ·​·​/​/​·​Set·​a·​deadline·​timer·​to·​expire·​immediately.​186 ·​·​/​/​·​Set·​a·​deadline·​timer·​to·​expire·​immediately.​
156 ·​·​asio:​:​steady_timer·​timer(io_context)​;​187 ·​·​asio:​:​steady_timer·​timer(io_context)​;​
157 ·​·​timer.​expires_at(asio:​:​steady_timer:​:​time_point:​:​min()​)​;​188 ·​·​timer.​expires_at(asio:​:​steady_timer:​:​clock_type:​:​time_point:​:​min()​)​;​
158 ·​·​timer.​async_wait(pri_queue.​wrap(42,​·​middle_priority_handl​er)​)​;​189 ·​·​timer.​async_wait(pri_queue.​wrap(42,​·​middle_priority_handl​er)​)​;​
159 190
160 ·​·​while·​(io_context.​run_one()​)​191 ·​·​while·​(io_context.​run_one()​)​
161 ·​·​{192 ·​·​{
162 ·​·​·​·​/​/​·​The·​custom·​invocation·​hook·​adds·​the·​handlers·​to·​the·​priority·​queue193 ·​·​·​·​/​/​·​The·​custom·​invocation·​hook·​adds·​the·​handlers·​to·​the·​priority·​queue
163 ·​·​·​·​/​/​·​rather·​than·​executing·​them·​from·​within·​the·​poll_one()​·​call.​194 ·​·​·​·​/​/​·​rather·​than·​executing·​them·​from·​within·​the·​poll_one()​·​call.​
164 ·​·​·​·​while·​(io_context.​poll_one()​)​195 ·​·​·​·​while·​(io_context.​poll_one()​)​
165 ·​·​·​·​·​·​;​196 ·​·​·​·​·​·​;​
166 197
167 ·​·​·​·​pri_queue.​execute_all()​;​198 ·​·​·​·​pri_queue.​execute_all()​;​
168 ·​·​}199 ·​·​}
169 200
170 ·​·​return·​0;​201 ·​·​return·​0;​
171 }202 }