Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3bad001

Browse files
committed
Adding Overloads for Options on connection::write
This commit enables the user to call 'write' with a special callbackfunction. Instead of just passing in a range, the user can then providea callback function once the writes are done. This solution allows forwriting handlers that by themselves can chunk up responses to conservememory on their own.An example streaming server using this approach should be doable.This implementation is largely untested, but builds.Also, setting the headers will by default send out the headers. In caseany errors are encountered at the time of the sending out of theheaders, that will be saved and then thrown in subsequent calls to'write'.This commit also contains a change to the macro that determines thebuffer size for connections, and for the chunk sizes of the linearizedbuffers to reflect the correct type.
1 parenta73d403 commit3bad001

File tree

2 files changed

+138
-9
lines changed

2 files changed

+138
-9
lines changed

‎boost/network/protocol/http/server/async_connection.hpp‎

Lines changed: 137 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@
1010
#include<boost/scope_exit.hpp>
1111
#include<boost/network/protocol/http/algorithms/linearize.hpp>
1212
#include<boost/network/utils/thread_pool.hpp>
13+
#include<boost/range/adaptor/sliced.hpp>
1314
#include<boost/range/algorithm/transform.hpp>
15+
#include<boost/range/algorithm/copy.hpp>
1416
#include<boost/asio/ip/tcp.hpp>
1517
#include<boost/asio/streambuf.hpp>
1618
#include<boost/asio/strand.hpp>
1719
#include<boost/asio/buffer.hpp>
20+
#include<boost/make_shared.hpp>
21+
#include<list>
22+
#include<vector>
1823
#include<iterator>
1924

2025
#ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE
@@ -53,6 +58,8 @@ namespace boost { namespace network { namespace http {
5358
, service_unavailable =503
5459
};
5560

61+
typedeftypename string<Tag>::type string_type;
62+
5663
async_connection(
5764
asio::io_service & io_service
5865
, Handler & handler
@@ -76,7 +83,7 @@ namespace boost { namespace network { namespace http {
7683
* then sent as soon as the first call to `write` or `flush` commences.
7784
*/
7885
template<classRange>
79-
voidset_headers(Range headers) {
86+
voidset_headers(Range headers,bool immediate =true) {
8087
if (headers_already_sent)
8188
boost::throw_exception(std::logic_error("Headers have already been sent."));
8289

@@ -99,6 +106,8 @@ namespace boost { namespace network { namespace http {
99106
stream <<consts::crlf();
100107
}
101108
stream <<consts::crlf();
109+
if (immediate)write_headers_only();
110+
102111
commit =true;
103112
}
104113

@@ -107,19 +116,34 @@ namespace boost { namespace network { namespace http {
107116
}
108117

109118
template<classRange>
110-
voidwrite(Range) {
111-
if (!headers_already_sent) {
112-
// TODO write out the headers that are already
113-
// linearized to the headers_buffer.
114-
}
115-
// linearize the range into a shared array
116-
// schedule a stranded asynchronous write
119+
voidwrite(Rangeconst & range) {
120+
write_impl(
121+
boost::make_iterator_range(range)
122+
,boost::bind(
123+
&async_connection<Tag,Handler>::default_error
124+
, async_connection<Tag,Handler>::shared_from_this()
125+
, _1
126+
)
127+
);
128+
}
129+
130+
template<classRange,classCallback>
131+
voidwrite(Rangeconst & range, Callbackconst & callback) {
132+
write_impl(
133+
boost::make_iterator_range(range)
134+
, callback
135+
);
117136
}
118137

119138
asio::ip::tcp::socket &socket() {return socket_; }
120139
utils::thread_pool &thread_pool() {return thread_pool_; }
121140

122141
private:
142+
143+
voiddefault_error(boost::system::error_codeconst & ec) {
144+
// TODO implement a sane default here, for now ignore the error
145+
}
146+
123147
asio::ip::tcp::socket socket_;
124148
asio::io_service::strand strand;
125149
Handler & handler;
@@ -129,6 +153,11 @@ namespace boost { namespace network { namespace http {
129153

130154
typedef boost::array<char, BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE>
131155
buffer_type;
156+
typedef boost::array<char, BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE>
157+
array;
158+
typedef std::list<shared_ptr<array> > array_list;
159+
typedef boost::shared_ptr<array_list> shared_array_list;
160+
typedef boost::shared_ptr<std::vector<asio::const_buffer> > shared_buffers;
132161
buffer_type read_buffer_;
133162
boost::uint16_t status;
134163

@@ -157,6 +186,106 @@ namespace boost { namespace network { namespace http {
157186
// FIXME -- damn all that work got wiped out because Jeni tripped on the power. :(
158187
}
159188

189+
template<classRange,classCallback>
190+
voidwrite_headers(Range range, Callback callback) {
191+
// TODO send out the headers, then once that's done
192+
// call the write again on the range and callback
193+
}
194+
195+
voidwrite_headers_only() {
196+
}
197+
198+
voidhandle_write_headers(boost::system::error_codeconst & ec) {
199+
if (ec) {
200+
// TODO signal somehow that there was an error so that subsequent
201+
// calls to write would throw an exception
202+
return;
203+
}
204+
headers_already_sent =true;
205+
}
206+
207+
voidhandle_write(
208+
boost::function<void(boost::system::error_codeconst &)> callback
209+
, shared_array_list temporaries
210+
, shared_buffers buffers
211+
, boost::system::error_codeconst & ec
212+
) {
213+
// we want to forget the temporaries and buffers
214+
thread_pool().post(boost::bind(callback, ec));
215+
}
216+
217+
template<classRange,classCallback>
218+
voidwrite_impl(Range range, Callback callback) {
219+
if (!headers_already_sent) {
220+
write_headers(range, callback);
221+
return;
222+
}
223+
224+
// linearize the whole range into a vector
225+
// of fixed-sized buffers, then schedule an asynchronous
226+
// write of these buffers -- make sure they are live
227+
// by making these linearized buffers shared and made
228+
// part of the completion handler.
229+
//
230+
// once the range has been linearized and sent, schedule
231+
// a wrapper to be called in the io_service's thread, that
232+
// will re-schedule the given callback into the thread pool
233+
// referred to here so that the io_service's thread can concentrate
234+
// on doing I/O.
235+
//
236+
237+
shared_array_list temporaries =
238+
boost::make_shared<array_list>();
239+
shared_buffers buffers =
240+
boost::make_shared<std::vector<asio::const_buffer> >(0);
241+
242+
std::size_t range_size =boost::distance(range);
243+
buffers->resize(
244+
(range_size / BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE)
245+
+ (range_size % BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE)
246+
);
247+
std::size_t slice_size =
248+
std::min(
249+
range_size,
250+
BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE
251+
);
252+
typename boost::range_iterator<Range>::type
253+
start =boost::begin(range)
254+
, end =boost::end(range);
255+
while (slice_size !=0) {
256+
using boost::adaptors::sliced;
257+
shared_ptr<array> new_array = make_shared<array>();
258+
boost::copy(
259+
range |sliced(0,slice_size)
260+
, new_array->begin()
261+
);
262+
temporaries->push_back(new_array);
263+
buffers->push_back(asio::buffer(new_array->data(), slice_size));
264+
std::advance(start, slice_size);
265+
range =boost::make_iterator_range(start, end);
266+
range_size =boost::distance(range);
267+
slice_size =std::min(range_size, BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE);
268+
}
269+
270+
if (!buffers->empty()) {
271+
boost::function<void(boost::system::error_codeconst &)> f = callback;
272+
asio::async_write(
273+
socket_
274+
, *buffers
275+
, strand.wrap(
276+
boost::bind(
277+
&async_connection<Tag,Handler>::handle_write
278+
, async_connection<Tag,Handler>::shared_from_this()
279+
, f
280+
, temporaries
281+
, buffers// keep these alive until the handler is called!
282+
, boost::asio::placeholders::error
283+
)
284+
)
285+
);
286+
}
287+
}
288+
160289
};
161290

162291
}/* http*/

‎boost/network/protocol/http/server/sync_connection.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#defineBOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_
1010

1111
#ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE
12-
#defineBOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE1024
12+
#defineBOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE1024uL
1313
#endif
1414

1515
#include<boost/enable_shared_from_this.hpp>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp