src/​examples/​cpp03/​allocation/​server.​cppsrc/​examples/​cpp11/​allocation/​server.​cpp
1 /​/​1 /​/​
2 /​/​·​server.​cpp2 /​/​·​server.​cpp
3 /​/​·​~~~~~~~~~~3 /​/​·​~~~~~~~~~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2015·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2015·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​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.​hpp>16 #include·​<utility>
16 #include·<boost/​enable_shared_from_th​is.​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·​allocation22 /​/​·​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,​·​the23 /​/​·​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_allocator25 class·​handler_allocator
28 ··​:​·​private·​boost:​:​noncopyable
29 {26 {
30 public:​27 public:​
31 ··​handler_allocator()​28 ··​handler_allocator()​
32 ····​:​·​in_use_(false)​29 ····​:​·​in_use_(false)​
33 ··​{30 ··​{
34 ··​}31 ··​}
35 32
33 ··​handler_allocator(con​st·​handler_allocator&)​·​=·​delete;​
34 ··​handler_allocator&·​operator=(const·​handler_allocator&)​·​=·​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 ····​else43 ····​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 ····​else55 ····​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 /​/​·​Wrapper·​class·​template·​for·​handler·​objects·​to·​allow·​handler·​memory69 /​/​·​Wrapper·​class·​template·​for·​handler·​objects·​to·​allow·​handler·​memory
70 /​/​·​allocation·​to·​be·​customised.​·​Calls·​to·​operator()​·​are·​forwarded·​to·​the70 /​/​·​allocation·​to·​be·​customised.​·​Calls·​to·​operator()​·​are·​forwarded·​to·​the
71 /​/​·​encapsulated·​handler.​71 /​/​·​encapsulated·​handler.​
72 template·​<typename·​Handler>72 template·​<typename·​Handler>
73 class·​custom_alloc_handler73 class·​custom_alloc_handler
74 {74 {
75 public:​75 public:​
76 ··​custom_alloc_handler(​handler_allocator&·​a,​·​Handler·​h)​76 ··​custom_alloc_handler(​handler_allocator&·​a,​·​Handler·​h)​
77 ····​:​·​allocator_(a)​,​77 ····​:​·​allocator_(a)​,​
78 ······​handler_(h)​78 ······​handler_(h)​
79 ··​{79 ··​{
80 ··​}80 ··​}
81 81
82 ··​template·​<typename·​Arg1>82 ··​template·​<typename·.​.​.​Args>
83 ··​void·​operator()​(Arg1·​arg1)​83 ··​void·​operator()​(Args&&.​.​.​·​args)​
84 ··{
85 ····handler_(arg1)​;​
86 ··}
87
88 ··template·<typename·Arg1,​·typename·Arg2>
89 ··void·operator()​(Arg1·arg1,​·Arg2·arg2)​
90 ··​{84 ··​{
91 ····​handler_(arg1,​·arg2)​;​85 ····​handler_(std:​:​forward<Args>(args)​.​.​.​)​;​
92 ··​}86 ··​}
93 87
94 ··​friend·​void*·​asio_handler_allocate​(std:​:​size_t·​size,​88 ··​friend·​void*·​asio_handler_allocate​(std:​:​size_t·​size,​
95 ······​custom_alloc_handler<​Handler>*·​this_handler)​89 ······​custom_alloc_handler<​Handler>*·​this_handler)​
96 ··​{90 ··​{
97 ····​return·​this_handler-​>allocator_.​allocate(size)​;​91 ····​return·​this_handler-​>allocator_.​allocate(size)​;​
98 ··​}92 ··​}
99 93
100 ··​friend·​void·​asio_handler_dealloca​te(void*·​pointer,​·​std:​:​size_t·​/​*size*/​,​94 ··​friend·​void·​asio_handler_dealloca​te(void*·​pointer,​·​std:​:​size_t·​/​*size*/​,​
101 ······​custom_alloc_handler<​Handler>*·​this_handler)​95 ······​custom_alloc_handler<​Handler>*·​this_handler)​
102 ··​{96 ··​{
103 ····​this_handler-​>allocator_.​deallocate(pointer)​;​97 ····​this_handler-​>allocator_.​deallocate(pointer)​;​
104 ··​}98 ··​}
105 99
106 private:​100 private:​
107 ··​handler_allocator&·​allocator_;​101 ··​handler_allocator&·​allocator_;​
108 ··​Handler·​handler_;​102 ··​Handler·​handler_;​
109 };​103 };​
110 104
111 /​/​·​Helper·​function·​to·​wrap·​a·​handler·​object·​to·​add·​custom·​allocation.​105 /​/​·​Helper·​function·​to·​wrap·​a·​handler·​object·​to·​add·​custom·​allocation.​
112 template·​<typename·​Handler>106 template·​<typename·​Handler>
113 inline·​custom_alloc_handler<​Handler>·​make_custom_alloc_han​dler(107 inline·​custom_alloc_handler<​Handler>·​make_custom_alloc_han​dler(
114 ····​handler_allocator&·​a,​·​Handler·​h)​108 ····​handler_allocator&·​a,​·​Handler·​h)​
115 {109 {
116 ··​return·​custom_alloc_handler<​Handler>(a,​·​h)​;​110 ··​return·​custom_alloc_handler<​Handler>(a,​·​h)​;​
117 }111 }
118 112
119 class·​session113 class·​session
120 ··​:​·​public·boost:​:​enable_shared_from_th​is<session>114 ··​:​·​public·​std:​:​enable_shared_from_th​is<session>
121 {115 {
122 public:​116 public:​
123 ··​session(asio:​:​io_service&·io_service)​117 ··​session(tcp:​:​socket·socket)​
124 ····​:​·​socket_(io_service)​118 ····​:​·​socket_(std:​:​move(socket)​)​
125 ··​{119 ··​{
126 ··​}120 ··​}
127 121
128 ··tcp:​:​socket&·​socket()​122 ··void·​start()​
129 ··​{123 ··​{
130 ····return·socket_;​124 ····do_read()​;​
131 ··​}125 ··​}
132 126
133 ··void·start()​127 private:​
128 ··​void·​do_read()​
134 ··​{129 ··​{
130 ····​auto·​self(shared_from_this​()​)​;​
135 ····​socket_.​async_read_some(asio:​:​buffer(data_)​,​131 ····​socket_.​async_read_some(asio:​:​buffer(data_)​,​
136 ········​make_custom_alloc_han​dler(allocator_,​132 ········​make_custom_alloc_han​dler(allocator_,​
137 ··········boost:​:​bind(&session:​:​handle_read,​133 ··········[this,​·self](std:​:​error_code·ec,​·std:​:​size_t·length)​
138 ············shared_from_this()​,​134 ··········{
139 ············asio:​:​placeholders:​:​error,​135 ············​if·(!ec)​
140 ············asio:​:​placeholders:​:​bytes_transferred)​)​)​;​136 ············{
141 ··}137 ··············do_write(length)​;​
142 138 ············}
143 ··void·handle_read(const·asio:​:​error_code&·error,​139 ··········})​)​;​
144 ······size_t·bytes_transferred)​
145 ··{
146 ····if·(!error)​
147 ····{
148 ······asio:​:​async_write(socket_,​
149 ··········asio:​:​buffer(data_,​·bytes_transferred)​,​
150 ··········make_custom_alloc_han​dler(allocator_,​
151 ············boost:​:​bind(&session:​:​handle_write,​
152 ··············shared_from_this()​,​
153 ··············asio:​:​placeholders:​:​error)​)​)​;​
154 ····}
155 ··​}140 ··​}
156 141
157 ··​void·handle_write(const·asio:​:​error_code&·error)​142 ··​void·​do_write(std:​:​size_t·length)​
158 ··​{143 ··​{
159 ····if·​(!error)​144 ····auto·self(shared_from_this​()​)​;​
160 ····{145 ····asio:​:​async_write(socket_,​·asio:​:​buffer(data_,​·length)​,​
161 ······socket_.​async_read_some(asio:​:​buffer(data_)​,​146 ········make_custom_alloc_han​dler(allocator_,​
162 ··········make_custom_alloc_han​dler(allocator_,​147 ··········[this,​·self](std:​:​error_code·ec,​·std:​:​size_t·/​*length*/​)​
163 ············boost:​:​bind(&session:​:​handle_read,​148 ··········{
164 ··············shared_from_this()​,​149 ············if·(!ec)​
165 ··············asio:​:​placeholders:​:​error,​150 ············{
166 ··············asio:​:​placeholders:​:​bytes_transferred)​)​)​;​151 ··············​do_read()​;​
167 ····​}152 ············​}
153 ··········​})​)​;​
168 ··​}154 ··​}
169 155
170 private:​
171 ··​/​/​·​The·​socket·​used·​to·​communicate·​with·​the·​client.​156 ··​/​/​·​The·​socket·​used·​to·​communicate·​with·​the·​client.​
172 ··​tcp:​:​socket·​socket_;​157 ··​tcp:​:​socket·​socket_;​
173 158
174 ··​/​/​·​Buffer·​used·​to·​store·​data·​received·​from·​the·​client.​159 ··​/​/​·​Buffer·​used·​to·​store·​data·​received·​from·​the·​client.​
175 ··boost:​:​array<char,​·​1024>·​data_;​160 ··​std:​:​array<char,​·​1024>·​data_;​
176 161
177 ··​/​/​·​The·​allocator·​to·​use·​for·​handler-​based·​custom·​memory·​allocation.​162 ··​/​/​·​The·​allocator·​to·​use·​for·​handler-​based·​custom·​memory·​allocation.​
178 ··​handler_allocator·​allocator_;​163 ··​handler_allocator·​allocator_;​
179 };​164 };​
180 165
181 typedef·​boost:​:​shared_ptr<session>·​session_ptr;​
182
183 class·​server166 class·​server
184 {167 {
185 public:​168 public:​
186 ··​server(asio:​:​io_service&·​io_service,​·​short·​port)​169 ··​server(asio:​:​io_service&·​io_service,​·​short·​port)​
187 ····​:​·​io_service_(io_servic​e)​,​170 ····​:​·acceptor_(io_service,​·tcp:​:​endpoint(tcp:​:​v4()​,​·port)​)​,​
188 ······acceptor_(io_service,​·tcp:​:​endpoint(tcp:​:​v4()​,​·port)​)​171 ······socket_(io_service)​
189 ··​{172 ··​{
190 ····session_ptr·new_session(new·session(io_service_)​)​;​173 ····do_accept()​;​
191 ····acceptor_.​async_accept(new_sess​ion-​>socket()​,​
192 ········boost:​:​bind(&server:​:​handle_accept,​·this,​·new_session,​
193 ··········asio:​:​placeholders:​:​error)​)​;​
194 ··​}174 ··​}
195 175
196 ··void·handle_accept(session​_ptr·new_session,​176 private:​
197 ······const·asio:​:​error_code&·error)​177 ··void·do_accept()​
198 ··​{178 ··​{
199 ····if·(!error)​179 ····acceptor_.​async_accept(socket_,​
200 ····{180 ········[this](std:​:​error_code·ec)​
201 ······new_session-​>start()​;​181 ········{
202 ····}182 ··········if·(!ec)​
183 ··········​{
184 ············​std:​:​make_shared<session>(​std:​:​move(socket_)​)​-​>start()​;​
185 ··········​}
203 186
204 ····new_session.​reset(new·session(io_service_)​)​;​187 ··········do_accept()​;​
205 ····acceptor_.​async_accept(new_sess​ion-​>socket()​,​188 ········})​;​
206 ········boost:​:​bind(&server:​:​handle_accept,​·this,​·new_session,​
207 ··········asio:​:​placeholders:​:​error)​)​;​
208 ··​}189 ··​}
209 190
210 private:​
211 ··​asio:​:​io_service&·​io_service_;​
212 ··​tcp:​:​acceptor·​acceptor_;​191 ··​tcp:​:​acceptor·​acceptor_;​
192 ··​tcp:​:​socket·​socket_;​
213 };​193 };​
214 194
215 int·​main(int·​argc,​·​char*·​argv[])​195 int·​main(int·​argc,​·​char*·​argv[])​
216 {196 {
217 ··​try197 ··​try
218 ··​{198 ··​{
219 ····​if·​(argc·​!=·​2)​199 ····​if·​(argc·​!=·​2)​
220 ····​{200 ····​{
221 ······​std:​:​cerr·​<<·​"Usage:​·​server·​<port>\n";​201 ······​std:​:​cerr·​<<·​"Usage:​·​server·​<port>\n";​
222 ······​return·​1;​202 ······​return·​1;​
223 ····​}203 ····​}
224 204
225 ····​asio:​:​io_service·​io_service;​205 ····​asio:​:​io_service·​io_service;​
226 206 ····server·s(io_service,​·std:​:​atoi(argv[1])​)​;​
227 ····using·namespace·std;​·/​/​·For·atoi.​
228 ····server·s(io_service,​·atoi(argv[1])​)​;​
229
230 ····​io_service.​run()​;​207 ····​io_service.​run()​;​
231 ··​}208 ··​}
232 ··​catch·​(std:​:​exception&·​e)​209 ··​catch·​(std:​:​exception&·​e)​
233 ··​{210 ··​{
234 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​211 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
235 ··​}212 ··​}
236 213
237 ··​return·​0;​214 ··​return·​0;​
238 }215 }