5 // Copyright (c) 2003-2017 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)
13 #include <boost/aligned_storage.hpp>
14 #include <boost/array.hpp>
15 #include <boost/bind.hpp>
16 #include <boost/enable_shared_from_this.hpp>
17 #include <boost/noncopyable.hpp>
18 #include <boost/shared_ptr.hpp>
19 #include <boost/asio.hpp>
21 using boost::asio::ip::tcp
;
23 // 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
25 // requests. If the memory is in use when an allocation request is made, the
26 // allocator delegates allocation to the global heap.
28 : private boost::noncopyable
36 void* allocate(std::size_t size
)
38 if (!in_use_
&& size
< storage_
.size
)
41 return storage_
.address();
45 return ::operator new(size
);
49 void deallocate(void* pointer
)
51 if (pointer
== storage_
.address())
57 ::operator delete(pointer
);
62 // Storage space used for handler-based custom memory allocation.
63 boost::aligned_storage
<1024> storage_
;
65 // Whether the handler-based custom allocation storage has been used.
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
73 class handler_allocator
78 explicit handler_allocator(handler_memory
& mem
)
84 handler_allocator(const handler_allocator
<U
>& other
)
85 : memory_(other
.memory_
)
92 typedef handler_allocator
<U
> other
;
95 bool operator==(const handler_allocator
& other
) const
97 return &memory_
== &other
.memory_
;
100 bool operator!=(const handler_allocator
& other
) const
102 return &memory_
!= &other
.memory_
;
105 T
* allocate(std::size_t n
) const
107 return static_cast<T
*>(memory_
.allocate(sizeof(T
) * n
));
110 void deallocate(T
* p
, std::size_t /*n*/) const
112 return memory_
.deallocate(p
);
116 // The underlying memory.
117 handler_memory
& memory_
;
120 // Wrapper class template for handler objects to allow handler memory
121 // allocation to be customised. The allocator_type typedef and get_allocator()
122 // member function are used by the asynchronous operations to obtain the
123 // allocator. Calls to operator() are forwarded to the encapsulated handler.
124 template <typename Handler
>
125 class custom_alloc_handler
128 typedef handler_allocator
<Handler
> allocator_type
;
130 custom_alloc_handler(handler_memory
& m
, Handler h
)
136 allocator_type
get_allocator() const
138 return allocator_type(memory_
);
141 template <typename Arg1
>
142 void operator()(Arg1 arg1
)
147 template <typename Arg1
, typename Arg2
>
148 void operator()(Arg1 arg1
, Arg2 arg2
)
150 handler_(arg1
, arg2
);
154 handler_memory
& memory_
;
158 // Helper function to wrap a handler object to add custom allocation.
159 template <typename Handler
>
160 inline custom_alloc_handler
<Handler
> make_custom_alloc_handler(
161 handler_memory
& m
, Handler h
)
163 return custom_alloc_handler
<Handler
>(m
, h
);
167 : public boost::enable_shared_from_this
<session
>
170 session(boost::asio::io_context
& io_context
)
171 : socket_(io_context
)
175 tcp::socket
& socket()
182 socket_
.async_read_some(boost::asio::buffer(data_
),
183 make_custom_alloc_handler(handler_memory_
,
184 boost::bind(&session::handle_read
,
186 boost::asio::placeholders::error
,
187 boost::asio::placeholders::bytes_transferred
)));
190 void handle_read(const boost::system::error_code
& error
,
191 size_t bytes_transferred
)
195 boost::asio::async_write(socket_
,
196 boost::asio::buffer(data_
, bytes_transferred
),
197 make_custom_alloc_handler(handler_memory_
,
198 boost::bind(&session::handle_write
,
200 boost::asio::placeholders::error
)));
204 void handle_write(const boost::system::error_code
& error
)
208 socket_
.async_read_some(boost::asio::buffer(data_
),
209 make_custom_alloc_handler(handler_memory_
,
210 boost::bind(&session::handle_read
,
212 boost::asio::placeholders::error
,
213 boost::asio::placeholders::bytes_transferred
)));
218 // The socket used to communicate with the client.
221 // Buffer used to store data received from the client.
222 boost::array
<char, 1024> data_
;
224 // The memory to use for handler-based custom memory allocation.
225 handler_memory handler_memory_
;
228 typedef boost::shared_ptr
<session
> session_ptr
;
233 server(boost::asio::io_context
& io_context
, short port
)
234 : io_context_(io_context
),
235 acceptor_(io_context
, tcp::endpoint(tcp::v4(), port
))
237 session_ptr
new_session(new session(io_context_
));
238 acceptor_
.async_accept(new_session
->socket(),
239 boost::bind(&server::handle_accept
, this, new_session
,
240 boost::asio::placeholders::error
));
243 void handle_accept(session_ptr new_session
,
244 const boost::system::error_code
& error
)
248 new_session
->start();
251 new_session
.reset(new session(io_context_
));
252 acceptor_
.async_accept(new_session
->socket(),
253 boost::bind(&server::handle_accept
, this, new_session
,
254 boost::asio::placeholders::error
));
258 boost::asio::io_context
& io_context_
;
259 tcp::acceptor acceptor_
;
262 int main(int argc
, char* argv
[])
268 std::cerr
<< "Usage: server <port>\n";
272 boost::asio::io_context io_context
;
274 using namespace std
; // For atoi.
275 server
s(io_context
, atoi(argv
[1]));
279 catch (std::exception
& e
)
281 std::cerr
<< "Exception: " << e
.what() << "\n";