| src/examples/cpp03/invocation/prioritised_handlers.cpp | src/examples/cpp11/invocation/prioritised_handlers.cpp |
| ⋮ | ⋮ |
| 1 | // | 1 | // |
| 2 | //·prioritised_handlers.cpp | 2 | //·prioritised_handlers.cpp |
| 3 | //·~~~~~~~~~~~~~~~~~~~~~~~~ | 3 | //·~~~~~~~~~~~~~~~~~~~~~~~~ |
| 4 | // | 4 | // |
| 5 | //·Copyright·(c)·2003-2018·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5 | //·Copyright·(c)·2003-2018·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) |
| 6 | // | 6 | // |
| 7 | //·Distributed·under·the·Boost·Software·License,·Version·1.0.·(See·accompanying | 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) | 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_queue·:·public·asio::execution_context | 18 | class·handler_priority_queue·:·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(priority,·function)); | 24 | ····std::unique_ptr<queued_handler_base>·handler( |
| | 25 | ········new·queued_handler<Function>( |
| | 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·executor | 40 | ··class·executor |
| 37 | ··{ | 41 | ··{ |
| 38 | ··public: | 42 | ··public: |
| 39 | ····executor(handler_priority_queue&·q,·int·p) | 43 | ····executor(handler_priority_queue&·q,·int·p) |
| 40 | ······:·context_(q),·priority_(p) | 44 | ······:·context_(q),·priority_(p) |
| 41 | ····{ | 45 | ····{ |
| 42 | ····} | 46 | ····} |
| 43 | | 47 | |
| 44 | ····handler_priority_queue&·context()·const | 48 | ····handler_priority_queue&·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&)·const | 54 | ····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&)·const | 60 | ····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&)·const | 66 | ····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)·const | 74 | ····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)·const | 79 | ····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_queue&·context_; | 85 | ····handler_priority_queue&·context_; |
| 82 | ····int·priority_; | 86 | ····int·priority_; |
| 83 | ··}; | 87 | ··}; |
| 84 | | 88 | |
| 85 | ··template·<typename·Handler> | 89 | ··template·<typename·Handler> |
| 86 | ··asio::executor_binder<Handler,·executor> | 90 | ··asio::executor_binder<Handler,·executor> |
| 87 | ··wrap(int·priority,·Handler·handler) | 91 | ··wrap(int·priority,·Handler·handler) |
| 88 | ··{ | 92 | ··{ |
| 89 | ····return·asio::bind_executor(executor(*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_handler | 98 | ··class·queued_handler_base |
| 94 | ··{ | 99 | ··{ |
| 95 | ··public: | 100 | ··public: |
| 96 | ····queued_handler(int·p,·boost::function<void()>·f) | 101 | ····queued_handler_base(int·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_handler_base>&·a, |
| | 113 | ········const·std::unique_ptr<queued_handler_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_handler_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_handler(const·asio::error_code&·/*ec*/) | 151 | void·middle_priority_handler(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_queue·pri_queue; | 173 | ··handler_priority_queue·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_context); | 181 | ··tcp::socket·server_socket(io_context); |
| 150 | ··acceptor.async_accept(server_socket, | 182 | ··acceptor.async_accept(pri_queue.wrap(100,·high_priority_handler)); |
| 151 | ······pri_queue.wrap(100,·high_priority_handler)); | |
| 152 | ··tcp::socket·client_socket(io_context); | 183 | ··tcp::socket·client_socket(io_context); |
| 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_handler)); | 189 | ··timer.async_wait(pri_queue.wrap(42,·middle_priority_handler)); |
| 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·queue | 193 | ····//·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 | } |