| src/examples/cpp03/allocation/server.cpp | src/examples/cpp11/allocation/server.cpp | 
| ⋮ | ⋮ | 
| 1  | // | 1  | // | 
| 2  | //·server.cpp | 2  | //·server.cpp | 
| 3  | //·~~~~~~~~~~ | 3  | //·~~~~~~~~~~ | 
| 4  | // | 4  | // | 
| 5  | //·Copyright·(c)·2003-2021·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5  | //·Copyright·(c)·2003-2021·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·<array> | 
| 11  | #include·<cstdlib> | 12  | #include·<cstdlib> | 
| 12  | #include·<iostream> | 13  | #include·<iostream> | 
| 13  | #include·<boost/aligned_storage.hpp> | 14  | #include·<memory> | 
| 14  | #include·<boost/array.hpp> | 15  | #include·<type_traits> | 
| 15  | #include·<boost/bind/bind.hpp> | 16  | #include·<utility> | 
| 16  | #include·<boost/enable_shared_from_this.hpp> |  | 
| 17  | #include·<boost/noncopyable.hpp> |  | 
| 18  | #include·<boost/shared_ptr.hpp> |  | 
| 19  | #include·"asio.hpp" | 17  | #include·"asio.hpp" | 
| 20  |  | 18  |  | 
| 21  | using·asio::ip::tcp; | 19  | using·asio::ip::tcp; | 
| 22  |  | 20  |  | 
| 23  | //·Class·to·manage·the·memory·to·be·used·for·handler-based·custom·allocation. | 21  | //·Class·to·manage·the·memory·to·be·used·for·handler-based·custom·allocation. | 
| 24  | //·It·contains·a·single·block·of·memory·which·may·be·returned·for·allocation | 22  | //·It·contains·a·single·block·of·memory·which·may·be·returned·for·allocation | 
| 25  | //·requests.·If·the·memory·is·in·use·when·an·allocation·request·is·made,·the | 23  | //·requests.·If·the·memory·is·in·use·when·an·allocation·request·is·made,·the | 
| 26  | //·allocator·delegates·allocation·to·the·global·heap. | 24  | //·allocator·delegates·allocation·to·the·global·heap. | 
| 27  | class·handler_memory | 25  | class·handler_memory | 
| 28  | ··:·private·boost::noncopyable |  | 
| 29  | { | 26  | { | 
| 30  | public: | 27  | public: | 
| 31  | ··handler_memory() | 28  | ··handler_memory() | 
| 32  | ····:·in_use_(false) | 29  | ····:·in_use_(false) | 
| 33  | ··{ | 30  | ··{ | 
| 34  | ··} | 31  | ··} | 
| 35  |  | 32  |  | 
|   | 33  | ··handler_memory(const·handler_memory&)·=·delete; | 
|   | 34  | ··handler_memory&·operator=(const·handler_memory&)·=·delete; | 
|   | 35  |  | 
| 36  | ··void*·allocate(std::size_t·size) | 36  | ··void*·allocate(std::size_t·size) | 
| 37  | ··{ | 37  | ··{ | 
| 38  | ····if·(!in_use_·&&·size·<·storage_.size) | 38  | ····if·(!in_use_·&&·size·<·sizeof(storage_)) | 
| 39  | ····{ | 39  | ····{ | 
| 40  | ······in_use_·=·true; | 40  | ······in_use_·=·true; | 
| 41  | ······return·storage_.address(); | 41  | ······return·&storage_; | 
| 42  | ····} | 42  | ····} | 
| 43  | ····else | 43  | ····else | 
| 44  | ····{ | 44  | ····{ | 
| 45  | ······return·::operator·new(size); | 45  | ······return·::operator·new(size); | 
| 46  | ····} | 46  | ····} | 
| 47  | ··} | 47  | ··} | 
| 48  |  | 48  |  | 
| 49  | ··void·deallocate(void*·pointer) | 49  | ··void·deallocate(void*·pointer) | 
| 50  | ··{ | 50  | ··{ | 
| 51  | ····if·(pointer·==·storage_.address()) | 51  | ····if·(pointer·==·&storage_) | 
| 52  | ····{ | 52  | ····{ | 
| 53  | ······in_use_·=·false; | 53  | ······in_use_·=·false; | 
| 54  | ····} | 54  | ····} | 
| 55  | ····else | 55  | ····else | 
| 56  | ····{ | 56  | ····{ | 
| 57  | ······::operator·delete(pointer); | 57  | ······::operator·delete(pointer); | 
| 58  | ····} | 58  | ····} | 
| 59  | ··} | 59  | ··} | 
| 60  |  | 60  |  | 
| 61  | private: | 61  | private: | 
| 62  | ··//·Storage·space·used·for·handler-based·custom·memory·allocation. | 62  | ··//·Storage·space·used·for·handler-based·custom·memory·allocation. | 
| 63  | ··boost::aligned_storage<1024>·storage_; | 63  | ··typename·std::aligned_storage<1024>::type·storage_; | 
| 64  |  | 64  |  | 
| 65  | ··//·Whether·the·handler-based·custom·allocation·storage·has·been·used. | 65  | ··//·Whether·the·handler-based·custom·allocation·storage·has·been·used. | 
| 66  | ··bool·in_use_; | 66  | ··bool·in_use_; | 
| 67  | }; | 67  | }; | 
| 68  |  | 68  |  | 
| 69  | //·The·allocator·to·be·associated·with·the·handler·objects.·This·allocator·only | 69  | //·The·allocator·to·be·associated·with·the·handler·objects.·This·allocator·only | 
| 70  | //·needs·to·satisfy·the·C++11·minimal·allocator·requirements,·plus·rebind·when | 70  | //·needs·to·satisfy·the·C++11·minimal·allocator·requirements. | 
| 71  | //·targeting·C++03. |  | 
| 72  | template·<typename·T> | 71  | template·<typename·T> | 
| 73  | class·handler_allocator | 72  | class·handler_allocator | 
| 74  | { | 73  | { | 
| 75  | public: | 74  | public: | 
| 76  | ··typedef·T·value_type; | 75  | ··using·value_type·=·T; | 
| 77  |  | 76  |  | 
| 78  | ··explicit·handler_allocator(handler_memory&·mem) | 77  | ··explicit·handler_allocator(handler_memory&·mem) | 
| 79  | ····:·memory_(mem) | 78  | ····:·memory_(mem) | 
| 80  | ··{ | 79  | ··{ | 
| 81  | ··} | 80  | ··} | 
| 82  |  | 81  |  | 
| 83  | ··template·<typename·U> | 82  | ··template·<typename·U> | 
| 84  | ··handler_allocator(const·handler_allocator<U>&·other) | 83  | ··handler_allocator(const·handler_allocator<U>&·other)·noexcept | 
| 85  | ····:·memory_(other.memory_) | 84  | ····:·memory_(other.memory_) | 
| 86  | ··{ | 85  | ··{ | 
| 87  | ··} | 86  | ··} | 
| 88  |  | 87  |  | 
| 89  | ··template·<typename·U> | 88  | ··bool·operator==(const·handler_allocator&·other)·const·noexcept | 
| 90  | ··struct·rebind |  | 
| 91  | ··{ |  | 
| 92  | ····typedef·handler_allocator<U>·other; |  | 
| 93  | ··}; |  | 
| 94  |  |  | 
| 95  | ··bool·operator==(const·handler_allocator&·other)·const |  | 
| 96  | ··{ | 89  | ··{ | 
| 97  | ····return·&memory_·==·&other.memory_; | 90  | ····return·&memory_·==·&other.memory_; | 
| 98  | ··} | 91  | ··} | 
| 99  |  | 92  |  | 
| 100  | ··bool·operator!=(const·handler_allocator&·other)·const | 93  | ··bool·operator!=(const·handler_allocator&·other)·const·noexcept | 
| 101  | ··{ | 94  | ··{ | 
| 102  | ····return·&memory_·!=·&other.memory_; | 95  | ····return·&memory_·!=·&other.memory_; | 
| 103  | ··} | 96  | ··} | 
| 104  |  | 97  |  | 
| 105  | ··T*·allocate(std::size_t·n)·const | 98  | ··T*·allocate(std::size_t·n)·const | 
| 106  | ··{ | 99  | ··{ | 
| 107  | ····return·static_cast<T*>(memory_.allocate(sizeof(T)·*·n)); | 100  | ····return·static_cast<T*>(memory_.allocate(sizeof(T)·*·n)); | 
| 108  | ··} | 101  | ··} | 
| 109  |  | 102  |  | 
| 110  | ··void·deallocate(T*·p,·std::size_t·/*n*/)·const | 103  | ··void·deallocate(T*·p,·std::size_t·/*n*/)·const | 
| 111  | ··{ | 104  | ··{ | 
| 112  | ····return·memory_.deallocate(p); | 105  | ····return·memory_.deallocate(p); | 
| 113  | ··} | 106  | ··} | 
| 114  |  | 107  |  | 
| 115  | //private: | 108  | private: | 
|   | 109  | ··template·<typename>·friend·class·handler_allocator; | 
|   | 110  |  | 
| 116  | ··//·The·underlying·memory. | 111  | ··//·The·underlying·memory. | 
| 117  | ··handler_memory&·memory_; | 112  | ··handler_memory&·memory_; | 
| 118  | }; | 113  | }; | 
| 119  |  | 114  |  | 
| 120  | //·Wrapper·class·template·for·handler·objects·to·allow·handler·memory | 115  | //·Wrapper·class·template·for·handler·objects·to·allow·handler·memory | 
| 121  | //·allocation·to·be·customised.·The·allocator_type·typedef·and·get_allocator() | 116  | //·allocation·to·be·customised.·The·allocator_type·type·and·get_allocator() | 
| 122  | //·member·function·are·used·by·the·asynchronous·operations·to·obtain·the | 117  | //·member·function·are·used·by·the·asynchronous·operations·to·obtain·the | 
| 123  | //·allocator.·Calls·to·operator()·are·forwarded·to·the·encapsulated·handler. | 118  | //·allocator.·Calls·to·operator()·are·forwarded·to·the·encapsulated·handler. | 
| 124  | template·<typename·Handler> | 119  | template·<typename·Handler> | 
| 125  | class·custom_alloc_handler | 120  | class·custom_alloc_handler | 
| 126  | { | 121  | { | 
| 127  | public: | 122  | public: | 
| 128  | ··typedef·handler_allocator<Handler>·allocator_type; | 123  | ··using·allocator_type·=·handler_allocator<Handler>; | 
| 129  |  | 124  |  | 
| 130  | ··custom_alloc_handler(handler_memory&·m,·Handler·h) | 125  | ··custom_alloc_handler(handler_memory&·m,·Handler·h) | 
| 131  | ····:·memory_(m), | 126  | ····:·memory_(m), | 
| 132  | ······handler_(h) | 127  | ······handler_(h) | 
| 133  | ··{ | 128  | ··{ | 
| 134  | ··} | 129  | ··} | 
| 135  |  | 130  |  | 
| 136  | ··allocator_type·get_allocator()·const | 131  | ··allocator_type·get_allocator()·const·noexcept | 
| 137  | ··{ | 132  | ··{ | 
| 138  | ····return·allocator_type(memory_); | 133  | ····return·allocator_type(memory_); | 
| 139  | ··} | 134  | ··} | 
| 140  |  | 135  |  | 
| 141  | ··template·<typename·Arg1> | 136  | ··template·<typename·...Args> | 
| 142  | ··void·operator()(Arg1·arg1) | 137  | ··void·operator()(Args&&...·args) | 
| 143  | ··{ |  | 
| 144  | ····handler_(arg1); |  | 
| 145  | ··} |  | 
| 146  |  |  | 
| 147  | ··template·<typename·Arg1,·typename·Arg2> |  | 
| 148  | ··void·operator()(Arg1·arg1,·Arg2·arg2) |  | 
| 149  | ··{ | 138  | ··{ | 
| 150  | ····handler_(arg1,·arg2); | 139  | ····handler_(std::forward<Args>(args)...); | 
| 151  | ··} | 140  | ··} | 
| 152  |  | 141  |  | 
| 153  | private: | 142  | private: | 
| 154  | ··handler_memory&·memory_; | 143  | ··handler_memory&·memory_; | 
| 155  | ··Handler·handler_; | 144  | ··Handler·handler_; | 
| 156  | }; | 145  | }; | 
| 157  |  | 146  |  | 
| 158  | //·Helper·function·to·wrap·a·handler·object·to·add·custom·allocation. | 147  | //·Helper·function·to·wrap·a·handler·object·to·add·custom·allocation. | 
| 159  | template·<typename·Handler> | 148  | template·<typename·Handler> | 
| 160  | inline·custom_alloc_handler<Handler>·make_custom_alloc_handler( | 149  | inline·custom_alloc_handler<Handler>·make_custom_alloc_handler( | 
| 161  | ····handler_memory&·m,·Handler·h) | 150  | ····handler_memory&·m,·Handler·h) | 
| 162  | { | 151  | { | 
| 163  | ··return·custom_alloc_handler<Handler>(m,·h); | 152  | ··return·custom_alloc_handler<Handler>(m,·h); | 
| 164  | } | 153  | } | 
| 165  |  | 154  |  | 
| 166  | class·session | 155  | class·session | 
| 167  | ··:·public·boost::enable_shared_from_this<session> | 156  | ··:·public·std::enable_shared_from_this<session> | 
| 168  | { | 157  | { | 
| 169  | public: | 158  | public: | 
| 170  | ··session(asio::io_context&·io_context) | 159  | ··session(tcp::socket·socket) | 
| 171  | ····:·socket_(io_context) | 160  | ····:·socket_(std::move(socket)) | 
| 172  | ··{ | 161  | ··{ | 
| 173  | ··} | 162  | ··} | 
| 174  |  | 163  |  | 
| 175  | ··tcp::socket&·socket() | 164  | ··void·start() | 
| 176  | ··{ | 165  | ··{ | 
| 177  | ····return·socket_; | 166  | ····do_read(); | 
| 178  | ··} | 167  | ··} | 
| 179  |  | 168  |  | 
| 180  | ··void·start() | 169  | private: | 
|   | 170  | ··void·do_read() | 
| 181  | ··{ | 171  | ··{ | 
|   | 172  | ····auto·self(shared_from_this()); | 
| 182  | ····socket_.async_read_some(asio::buffer(data_), | 173  | ····socket_.async_read_some(asio::buffer(data_), | 
| 183  | ········make_custom_alloc_handler(handler_memory_, | 174  | ········make_custom_alloc_handler(handler_memory_, | 
| 184  | ··········boost::bind(&session::handle_read, | 175  | ··········[this,·self](std::error_code·ec,·std::size_t·length) | 
| 185  | ············shared_from_this(), | 176  | ··········{ | 
| 186  | ············asio::placeholders::error, | 177  | ············if·(!ec) | 
| 187  | ············asio::placeholders::bytes_transferred))); | 178  | ············{ | 
| 188  | ··} | 179  | ··············do_write(length); | 
| 189  |  | 180  | ············} | 
| 190  | ··void·handle_read(const·asio::error_code&·error, | 181  | ··········})); | 
| 191  | ······size_t·bytes_transferred) |  | 
| 192  | ··{ |  | 
| 193  | ····if·(!error) |  | 
| 194  | ····{ |  | 
| 195  | ······asio::async_write(socket_, |  | 
| 196  | ··········asio::buffer(data_,·bytes_transferred), |  | 
| 197  | ··········make_custom_alloc_handler(handler_memory_, |  | 
| 198  | ············boost::bind(&session::handle_write, |  | 
| 199  | ··············shared_from_this(), |  | 
| 200  | ··············asio::placeholders::error))); |  | 
| 201  | ····} |  | 
| 202  | ··} | 182  | ··} | 
| 203  |  | 183  |  | 
| 204  | ··void·handle_write(const·asio::error_code&·error) | 184  | ··void·do_write(std::size_t·length) | 
| 205  | ··{ | 185  | ··{ | 
| 206  | ····if·(!error) | 186  | ····auto·self(shared_from_this()); | 
| 207  | ····{ | 187  | ····asio::async_write(socket_,·asio::buffer(data_,·length), | 
| 208  | ······socket_.async_read_some(asio::buffer(data_), | 188  | ········make_custom_alloc_handler(handler_memory_, | 
| 209  | ··········make_custom_alloc_handler(handler_memory_, | 189  | ··········[this,·self](std::error_code·ec,·std::size_t·/*length*/) | 
| 210  | ············boost::bind(&session::handle_read, | 190  | ··········{ | 
| 211  | ··············shared_from_this(), | 191  | ············if·(!ec) | 
| 212  | ··············asio::placeholders::error, | 192  | ············{ | 
| 213  | ··············asio::placeholders::bytes_transferred))); | 193  | ··············do_read(); | 
| 214  | ····} | 194  | ············} | 
|   | 195  | ··········})); | 
| 215  | ··} | 196  | ··} | 
| 216  |  | 197  |  | 
| 217  | private: |  | 
| 218  | ··//·The·socket·used·to·communicate·with·the·client. | 198  | ··//·The·socket·used·to·communicate·with·the·client. | 
| 219  | ··tcp::socket·socket_; | 199  | ··tcp::socket·socket_; | 
| 220  |  | 200  |  | 
| 221  | ··//·Buffer·used·to·store·data·received·from·the·client. | 201  | ··//·Buffer·used·to·store·data·received·from·the·client. | 
| 222  | ··boost::array<char,·1024>·data_; | 202  | ··std::array<char,·1024>·data_; | 
| 223  |  | 203  |  | 
| 224  | ··//·The·memory·to·use·for·handler-based·custom·memory·allocation. | 204  | ··//·The·memory·to·use·for·handler-based·custom·memory·allocation. | 
| 225  | ··handler_memory·handler_memory_; | 205  | ··handler_memory·handler_memory_; | 
| 226  | }; | 206  | }; | 
| 227  |  | 207  |  | 
| 228  | typedef·boost::shared_ptr<session>·session_ptr; |  | 
| 229  |  |  | 
| 230  | class·server | 208  | class·server | 
| 231  | { | 209  | { | 
| 232  | public: | 210  | public: | 
| 233  | ··server(asio::io_context&·io_context,·short·port) | 211  | ··server(asio::io_context&·io_context,·short·port) | 
| 234  | ····:·io_context_(io_context), | 212  | ····:·acceptor_(io_context,·tcp::endpoint(tcp::v4(),·port)) | 
| 235  | ······acceptor_(io_context,·tcp::endpoint(tcp::v4(),·port)) |  | 
| 236  | ··{ | 213  | ··{ | 
| 237  | ····session_ptr·new_session(new·session(io_context_)); | 214  | ····do_accept(); | 
| 238  | ····acceptor_.async_accept(new_session->socket(), |  | 
| 239  | ········boost::bind(&server::handle_accept,·this,·new_session, |  | 
| 240  | ··········asio::placeholders::error)); |  | 
| 241  | ··} | 215  | ··} | 
| 242  |  | 216  |  | 
| 243  | ··void·handle_accept(session_ptr·new_session, | 217  | private: | 
| 244  | ······const·asio::error_code&·error) | 218  | ··void·do_accept() | 
| 245  | ··{ | 219  | ··{ | 
| 246  | ····if·(!error) | 220  | ····acceptor_.async_accept( | 
| 247  | ····{ | 221  | ········[this](std::error_code·ec,·tcp::socket·socket) | 
| 248  | ······new_session->start(); | 222  | ········{ | 
| 249  | ····} | 223  | ··········if·(!ec) | 
|   | 224  | ··········{ | 
|   | 225  | ············std::make_shared<session>(std::move(socket))->start(); | 
|   | 226  | ··········} | 
| 250  |  | 227  |  | 
| 251  | ····new_session.reset(new·session(io_context_)); | 228  | ··········do_accept(); | 
| 252  | ····acceptor_.async_accept(new_session->socket(), | 229  | ········}); | 
| 253  | ········boost::bind(&server::handle_accept,·this,·new_session, |  | 
| 254  | ··········asio::placeholders::error)); |  | 
| 255  | ··} | 230  | ··} | 
| 256  |  | 231  |  | 
| 257  | private: |  | 
| 258  | ··asio::io_context&·io_context_; |  | 
| 259  | ··tcp::acceptor·acceptor_; | 232  | ··tcp::acceptor·acceptor_; | 
| 260  | }; | 233  | }; | 
| 261  |  | 234  |  | 
| 262  | int·main(int·argc,·char*·argv[]) | 235  | int·main(int·argc,·char*·argv[]) | 
| 263  | { | 236  | { | 
| 264  | ··try | 237  | ··try | 
| 265  | ··{ | 238  | ··{ | 
| 266  | ····if·(argc·!=·2) | 239  | ····if·(argc·!=·2) | 
| 267  | ····{ | 240  | ····{ | 
| 268  | ······std::cerr·<<·"Usage:·server·<port>\n"; | 241  | ······std::cerr·<<·"Usage:·server·<port>\n"; | 
| 269  | ······return·1; | 242  | ······return·1; | 
| 270  | ····} | 243  | ····} | 
| 271  |  | 244  |  | 
| 272  | ····asio::io_context·io_context; | 245  | ····asio::io_context·io_context; | 
| 273  |  | 246  | ····server·s(io_context,·std::atoi(argv[1])); | 
| 274  | ····using·namespace·std;·//·For·atoi. |  | 
| 275  | ····server·s(io_context,·atoi(argv[1])); |  | 
| 276  |  |  | 
| 277  | ····io_context.run(); | 247  | ····io_context.run(); | 
| 278  | ··} | 248  | ··} | 
| 279  | ··catch·(std::exception&·e) | 249  | ··catch·(std::exception&·e) | 
| 280  | ··{ | 250  | ··{ | 
| 281  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 251  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 
| 282  | ··} | 252  | ··} | 
| 283  |  | 253  |  | 
| 284  | ··return·0; | 254  | ··return·0; | 
| 285  | } | 255  | } |