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-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2022·​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 ·​·​{
92 ·​·​·​·​typedef·​handler_allocator<U>·​other;​
93 ·​·​};​
94
95 ·​·​bool·​operator==(const·​handler_allocator&·​other)​·​const
96 ·​·​{89 ·​·​{
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 ·​·​·​·​:​·​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 ·​·​·​·​·​·​·​·​·​·​·​·​{
143 ·​·​}140 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​do_write(length)​;​
144 141 ·​·​·​·​·​·​·​·​·​·​·​·​}
145 ·​·​void·​handle_read(const·​asio:​:​error_code&·​error,​142 ·​·​·​·​·​·​·​·​·​·​})​)​;​
146 ·​·​·​·​·​·​size_t·​bytes_transferred)​
147 ·​·​{
148 ·​·​·​·​if·​(!error)​
149 ·​·​·​·​{
150 ·​·​·​·​·​·​asio:​:​async_write(socket_,​
151 ·​·​·​·​·​·​·​·​·​·​asio:​:​buffer(data_,​·​bytes_transferred)​,​
152 ·​·​·​·​·​·​·​·​·​·​asio:​:​bind_allocator(
153 ·​·​·​·​·​·​·​·​·​·​·​·​handler_allocator<int​>(handler_memory_)​,​
154 ·​·​·​·​·​·​·​·​·​·​·​·​boost:​:​bind(&session:​:​handle_write,​
155 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​shared_from_this()​,​
156 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error)​)​)​;​
157 ·​·​·​·​}
158 ·​·​}143 ·​·​}
159 144
160 ·​·​void·​handle_write(const·​asio:​:​error_code&·​error)​145 ·​·​void·​do_write(std:​:​size_t·​length)​
161 ·​·​{146 ·​·​{
162 ·​·​·​·​if·​(!error)​147 ·​·​·​·​auto·​self(shared_from_this​()​)​;​
163 ·​·​·​·​{148 ·​·​·​·​asio:​:​async_write(socket_,​·​asio:​:​buffer(data_,​·​length)​,​
164 ·​·​·​·​·​·​socket_.​async_read_some(asio:​:​buffer(data_)​,​149 ·​·​·​·​·​·​·​·​asio:​:​bind_allocator(
165 ·​·​·​·​·​·​·​·​·​·​asio:​:​bind_allocator(150 ·​·​·​·​·​·​·​·​·​·​handler_allocator<int​>(handler_memory_)​,​
166 ·​·​·​·​·​·​·​·​·​·​·​·​handler_allocator<int​>(handler_memory_)​,​151 ·​·​·​·​·​·​·​·​·​·​[this,​·​self](std:​:​error_code·​ec,​·​std:​:​size_t·​/​*length*/​)​
167 ·​·​·​·​·​·​·​·​·​·​·​·​boost:​:​bind(&session:​:​handle_read,​152 ·​·​·​·​·​·​·​·​·​·​{
168 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​shared_from_this()​,​153 ·​·​·​·​·​·​·​·​·​·​·​·​if·​(!ec)​
169 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error,​154 ·​·​·​·​·​·​·​·​·​·​·​·​{
170 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​bytes_transferred)​)​)​;​155 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​do_read()​;​
171 ·​·​·​·​}156 ·​·​·​·​·​·​·​·​·​·​·​·​}
157 ·​·​·​·​·​·​·​·​·​·​})​)​;​
172 ·​·​}158 ·​·​}
173 159
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·​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 }