5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
15 #include <type_traits>
17 #include <boost/asio.hpp>
19 using boost::asio::ip::tcp
;
21 // Class to manage the memory to be used for handler-based custom allocation.
22 // It contains a single block of memory which may be returned for allocation
23 // requests. If the memory is in use when an allocation request is made, the
24 // allocator delegates allocation to the global heap.
25 class handler_allocator
33 handler_allocator(const handler_allocator
&) = delete;
34 handler_allocator
& operator=(const handler_allocator
&) = delete;
36 void* allocate(std::size_t size
)
38 if (!in_use_
&& size
< sizeof(storage_
))
45 return ::operator new(size
);
49 void deallocate(void* pointer
)
51 if (pointer
== &storage_
)
57 ::operator delete(pointer
);
62 // Storage space used for handler-based custom memory allocation.
63 typename
std::aligned_storage
<1024>::type storage_
;
65 // Whether the handler-based custom allocation storage has been used.
69 // Wrapper class template for handler objects to allow handler memory
70 // allocation to be customised. Calls to operator() are forwarded to the
71 // encapsulated handler.
72 template <typename Handler
>
73 class custom_alloc_handler
76 custom_alloc_handler(handler_allocator
& a
, Handler h
)
82 template <typename
...Args
>
83 void operator()(Args
&&... args
)
85 handler_(std::forward
<Args
>(args
)...);
88 friend void* asio_handler_allocate(std::size_t size
,
89 custom_alloc_handler
<Handler
>* this_handler
)
91 return this_handler
->allocator_
.allocate(size
);
94 friend void asio_handler_deallocate(void* pointer
, std::size_t /*size*/,
95 custom_alloc_handler
<Handler
>* this_handler
)
97 this_handler
->allocator_
.deallocate(pointer
);
101 handler_allocator
& allocator_
;
105 // Helper function to wrap a handler object to add custom allocation.
106 template <typename Handler
>
107 inline custom_alloc_handler
<Handler
> make_custom_alloc_handler(
108 handler_allocator
& a
, Handler h
)
110 return custom_alloc_handler
<Handler
>(a
, h
);
114 : public std::enable_shared_from_this
<session
>
117 session(tcp::socket socket
)
118 : socket_(std::move(socket
))
130 auto self(shared_from_this());
131 socket_
.async_read_some(boost::asio::buffer(data_
),
132 make_custom_alloc_handler(allocator_
,
133 [this, self
](boost::system::error_code ec
, std::size_t length
)
142 void do_write(std::size_t length
)
144 auto self(shared_from_this());
145 boost::asio::async_write(socket_
, boost::asio::buffer(data_
, length
),
146 make_custom_alloc_handler(allocator_
,
147 [this, self
](boost::system::error_code ec
, std::size_t /*length*/)
156 // The socket used to communicate with the client.
159 // Buffer used to store data received from the client.
160 std::array
<char, 1024> data_
;
162 // The allocator to use for handler-based custom memory allocation.
163 handler_allocator allocator_
;
169 server(boost::asio::io_service
& io_service
, short port
)
170 : acceptor_(io_service
, tcp::endpoint(tcp::v4(), port
)),
179 acceptor_
.async_accept(socket_
,
180 [this](boost::system::error_code ec
)
184 std::make_shared
<session
>(std::move(socket_
))->start();
191 tcp::acceptor acceptor_
;
195 int main(int argc
, char* argv
[])
201 std::cerr
<< "Usage: server <port>\n";
205 boost::asio::io_service io_service
;
206 server
s(io_service
, std::atoi(argv
[1]));
209 catch (std::exception
& e
)
211 std::cerr
<< "Exception: " << e
.what() << "\n";