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 }