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-​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·​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/​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_memory25 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 ····​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 /​/​·​The·​allocator·​to·​be·​associated·​with·​the·​handler·​objects.​·​This·​allocator·​only69 /​/​·​The·​allocator·​to·​be·​associated·​with·​the·​handler·​objects.​·​This·​allocator·​only
70 /​/​·​needs·​to·​satisfy·​the·​C++11·​minimal·​allocator·​requirements,​·plus·rebind·when70 /​/​·​needs·​to·​satisfy·​the·​C++11·​minimal·​allocator·​requirements.​
71 /​/​·targeting·C++03.​
72 template·​<typename·​T>71 template·​<typename·​T>
73 class·​handler_allocator72 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(han​dler_memory&·​mem)​77 ··​explicit·​handler_allocator(han​dler_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(con​st·​handler_allocator<U>&​·​other)​83 ··​handler_allocator(con​st·​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)​·​const93 ··​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)​·​const98 ··​T*·​allocate(std:​:​size_t·​n)​·​const
106 ··​{99 ··​{
107 ····​return·​static_cast<T*>(memor​y_.​allocate(sizeof(T)​·​*·​n)​)​;​100 ····​return·​static_cast<T*>(memor​y_.​allocate(sizeof(T)​·​*·​n)​)​;​
108 ··​}101 ··​}
109 102
110 ··​void·​deallocate(T*·​p,​·​std:​:​size_t·​/​*n*/​)​·​const103 ··​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·​session115 class·​session
121 ··​:​·​public·boost:​:​enable_shared_from_th​is<session>116 ··​:​·​public·​std:​:​enable_shared_from_th​is<session>
122 {117 {
123 public:​118 public:​
124 ··​session(asio:​:​io_context&·io_context)​119 ··​session(tcp:​:​socket·socket)​
125 ····​:​·​local_socket(io_context)​120 ····​:​·​local_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 ····​local_socket.​async_read_some(asio:​:​buffer(data_)​,​133 ····​local_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 ······​local_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·​local_socket;​161 ··​tcp:​:​socket·​local_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·​server170 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_contex​t)​,​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_sess​ion-​>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_sess​ion-​>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 ··​try199 ··​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 }