| 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-2023·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5  | //·Copyright·(c)·2003-2023·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  | ··{ | 89  | ··{ | 
| 92  | ····typedef·handler_allocator<U>·other; |  | 
| 93  | ··}; |  | 
| 94  |  |  | 
| 95  | ··bool·operator==(const·handler_allocator&·other)·const |  | 
| 96  | ··{ |  | 
| 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  | class·session | 115  | class·session | 
| 121  | ··:·public·boost::enable_shared_from_this<session> | 116  | ··:·public·std::enable_shared_from_this<session> | 
| 122  | { | 117  | { | 
| 123  | public: | 118  | public: | 
| 124  | ··session(asio::io_context&·io_context) | 119  | ··session(tcp::socket·socket) | 
| 125  | ····:·socket_(io_context) | 120  | ····:·socket_(std::move(socket)) | 
| 126  | ··{ | 121  | ··{ | 
| 127  | ··} | 122  | ··} | 
| 128  |  | 123  |  | 
| 129  | ··tcp::socket&·socket() | 124  | ··void·start() | 
| 130  | ··{ | 125  | ··{ | 
| 131  | ····return·socket_; | 126  | ····do_read(); | 
| 132  | ··} | 127  | ··} | 
| 133  |  | 128  |  | 
| 134  | ··void·start() | 129  | private: | 
|   | 130  | ··void·do_read() | 
| 135  | ··{ | 131  | ··{ | 
|   | 132  | ····auto·self(shared_from_this()); | 
| 136  | ····socket_.async_read_some(asio::buffer(data_), | 133  | ····socket_.async_read_some(asio::buffer(data_), | 
| 137  | ········asio::bind_allocator( | 134  | ········asio::bind_allocator( | 
| 138  | ··········handler_allocator<int>(handler_memory_), | 135  | ··········handler_allocator<int>(handler_memory_), | 
| 139  | ··········boost::bind(&session::handle_read, | 136  | ··········[this,·self](std::error_code·ec,·std::size_t·length) | 
| 140  | ············shared_from_this(), | 137  | ··········{ | 
| 141  | ············asio::placeholders::error, | 138  | ············if·(!ec) | 
| 142  | ············asio::placeholders::bytes_transferred))); | 139  | ············{ | 
|   | 140  | ··············do_write(length); | 
|   | 141  | ············} | 
|   | 142  | ··········})); | 
| 143  | ··} | 143  | ··} | 
| 144  |  | 144  |  | 
| 145  | ··void·handle_read(const·asio::error_code&·error, | 145  | ··void·do_write(std::size_t·length) | 
| 146  | ······size_t·bytes_transferred) |  | 
| 147  | ··{ | 146  | ··{ | 
| 148  | ····if·(!error) | 147  | ····auto·self(shared_from_this()); | 
| 149  | ····{ | 148  | ····asio::async_write(socket_,·asio::buffer(data_,·length), | 
| 150  | ······asio::async_write(socket_, | 149  | ········asio::bind_allocator( | 
| 151  | ··········asio::buffer(data_,·bytes_transferred), | 150  | ··········handler_allocator<int>(handler_memory_), | 
| 152  | ··········asio::bind_allocator( | 151  | ··········[this,·self](std::error_code·ec,·std::size_t·/*length*/) | 
| 153  | ············handler_allocator<int>(handler_memory_), | 152  | ··········{ | 
| 154  | ············boost::bind(&session::handle_write, | 153  | ············if·(!ec) | 
| 155  | ··············shared_from_this(), | 154  | ············{ | 
| 156  | ··············asio::placeholders::error))); | 155  | ··············do_read(); | 
| 157  | ····} | 156  | ············} | 
|   | 157  | ··········})); | 
| 158  | ··} | 158  | ··} | 
| 159  |  | 159  |  | 
| 160  | ··void·handle_write(const·asio::error_code&·error) |  | 
| 161  | ··{ |  | 
| 162  | ····if·(!error) |  | 
| 163  | ····{ |  | 
| 164  | ······socket_.async_read_some(asio::buffer(data_), |  | 
| 165  | ··········asio::bind_allocator( |  | 
| 166  | ············handler_allocator<int>(handler_memory_), |  | 
| 167  | ············boost::bind(&session::handle_read, |  | 
| 168  | ··············shared_from_this(), |  | 
| 169  | ··············asio::placeholders::error, |  | 
| 170  | ··············asio::placeholders::bytes_transferred))); |  | 
| 171  | ····} |  | 
| 172  | ··} |  | 
| 173  |  |  | 
| 174  | private: |  | 
| 175  | ··//·The·socket·used·to·communicate·with·the·client. | 160  | ··//·The·socket·used·to·communicate·with·the·client. | 
| 176  | ··tcp::socket·socket_; | 161  | ··tcp::socket·socket_; | 
| 177  |  | 162  |  | 
| 178  | ··//·Buffer·used·to·store·data·received·from·the·client. | 163  | ··//·Buffer·used·to·store·data·received·from·the·client. | 
| 179  | ··boost::array<char,·1024>·data_; | 164  | ··std::array<char,·1024>·data_; | 
| 180  |  | 165  |  | 
| 181  | ··//·The·memory·to·use·for·handler-based·custom·memory·allocation. | 166  | ··//·The·memory·to·use·for·handler-based·custom·memory·allocation. | 
| 182  | ··handler_memory·handler_memory_; | 167  | ··handler_memory·handler_memory_; | 
| 183  | }; | 168  | }; | 
| 184  |  | 169  |  | 
| 185  | typedef·boost::shared_ptr<session>·session_ptr; |  | 
| 186  |  |  | 
| 187  | class·server | 170  | class·server | 
| 188  | { | 171  | { | 
| 189  | public: | 172  | public: | 
| 190  | ··server(asio::io_context&·io_context,·short·port) | 173  | ··server(asio::io_context&·io_context,·short·port) | 
| 191  | ····:·io_context_(io_context), | 174  | ····:·acceptor_(io_context,·tcp::endpoint(tcp::v4(),·port)) | 
| 192  | ······acceptor_(io_context,·tcp::endpoint(tcp::v4(),·port)) |  | 
| 193  | ··{ | 175  | ··{ | 
| 194  | ····session_ptr·new_session(new·session(io_context_)); | 176  | ····do_accept(); | 
| 195  | ····acceptor_.async_accept(new_session->socket(), |  | 
| 196  | ········boost::bind(&server::handle_accept,·this,·new_session, |  | 
| 197  | ··········asio::placeholders::error)); |  | 
| 198  | ··} | 177  | ··} | 
| 199  |  | 178  |  | 
| 200  | ··void·handle_accept(session_ptr·new_session, | 179  | private: | 
| 201  | ······const·asio::error_code&·error) | 180  | ··void·do_accept() | 
| 202  | ··{ | 181  | ··{ | 
| 203  | ····if·(!error) | 182  | ····acceptor_.async_accept( | 
| 204  | ····{ | 183  | ········[this](std::error_code·ec,·tcp::socket·socket) | 
| 205  | ······new_session->start(); | 184  | ········{ | 
| 206  | ····} | 185  | ··········if·(!ec) | 
|   | 186  | ··········{ | 
|   | 187  | ············std::make_shared<session>(std::move(socket))->start(); | 
|   | 188  | ··········} | 
| 207  |  | 189  |  | 
| 208  | ····new_session.reset(new·session(io_context_)); | 190  | ··········do_accept(); | 
| 209  | ····acceptor_.async_accept(new_session->socket(), | 191  | ········}); | 
| 210  | ········boost::bind(&server::handle_accept,·this,·new_session, |  | 
| 211  | ··········asio::placeholders::error)); |  | 
| 212  | ··} | 192  | ··} | 
| 213  |  | 193  |  | 
| 214  | private: |  | 
| 215  | ··asio::io_context&·io_context_; |  | 
| 216  | ··tcp::acceptor·acceptor_; | 194  | ··tcp::acceptor·acceptor_; | 
| 217  | }; | 195  | }; | 
| 218  |  | 196  |  | 
| 219  | int·main(int·argc,·char*·argv[]) | 197  | int·main(int·argc,·char*·argv[]) | 
| 220  | { | 198  | { | 
| 221  | ··try | 199  | ··try | 
| 222  | ··{ | 200  | ··{ | 
| 223  | ····if·(argc·!=·2) | 201  | ····if·(argc·!=·2) | 
| 224  | ····{ | 202  | ····{ | 
| 225  | ······std::cerr·<<·"Usage:·server·<port>\n"; | 203  | ······std::cerr·<<·"Usage:·server·<port>\n"; | 
| 226  | ······return·1; | 204  | ······return·1; | 
| 227  | ····} | 205  | ····} | 
| 228  |  | 206  |  | 
| 229  | ····asio::io_context·io_context; | 207  | ····asio::io_context·io_context; | 
| 230  |  | 208  | ····server·s(io_context,·std::atoi(argv[1])); | 
| 231  | ····using·namespace·std;·//·For·atoi. |  | 
| 232  | ····server·s(io_context,·atoi(argv[1])); |  | 
| 233  |  |  | 
| 234  | ····io_context.run(); | 209  | ····io_context.run(); | 
| 235  | ··} | 210  | ··} | 
| 236  | ··catch·(std::exception&·e) | 211  | ··catch·(std::exception&·e) | 
| 237  | ··{ | 212  | ··{ | 
| 238  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 213  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 
| 239  | ··} | 214  | ··} | 
| 240  |  | 215  |  | 
| 241  | ··return·0; | 216  | ··return·0; | 
| 242  | } | 217  | } |