Skip to content

Commit 37efecc

Browse files
committed
Introduced non-copying async_connection::write_vec()
write_impl() rewritten using write_vec_impl(). Fixed race on user data in write_impl() by linearizing data before scheduling any async operations.
1 parent 6abafda commit 37efecc

File tree

1 file changed

+44
-47
lines changed

1 file changed

+44
-47
lines changed

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

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,15 @@ namespace boost { namespace network { namespace http {
214214
void write(Range const & range, Callback const & callback) {
215215
lock_guard lock(headers_mutex);
216216
if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered));
217-
boost::function<void(boost::system::error_code)> f = callback;
218217
write_impl(boost::make_iterator_range(range), callback);
219218
}
220219

220+
template <class ConstBufferSeq, class Callback>
221+
void write_vec(ConstBufferSeq const & seq, Callback const & callback)
222+
{
223+
write_vec_impl(seq, callback, shared_array_list(), shared_buffers());
224+
}
225+
221226
private:
222227
typedef boost::array<char, BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE> buffer_type;
223228

@@ -488,15 +493,6 @@ namespace boost { namespace network { namespace http {
488493

489494
void do_nothing() {}
490495

491-
template <class Range>
492-
void continue_write(Range range, boost::function<void(boost::system::error_code)> callback) {
493-
thread_pool().post(
494-
boost::bind(
495-
&async_connection<Tag,Handler>::write_impl<Range>
496-
, async_connection<Tag,Handler>::shared_from_this()
497-
, range, callback));
498-
}
499-
500496
template <class Callback>
501497
void write_first_line(Callback callback) {
502498
lock_guard lock(headers_mutex);
@@ -581,27 +577,6 @@ namespace boost { namespace network { namespace http {
581577

582578
template <class Range>
583579
void write_impl(Range range, boost::function<void(boost::system::error_code)> callback) {
584-
lock_guard lock(headers_mutex);
585-
boost::function<void(boost::system::error_code)> callback_function =
586-
callback;
587-
588-
if (!headers_already_sent && !headers_in_progress) {
589-
write_headers_only(
590-
boost::bind(
591-
&async_connection<Tag,Handler>::continue_write<Range>
592-
, async_connection<Tag,Handler>::shared_from_this()
593-
, range, callback_function
594-
));
595-
return;
596-
} else if (headers_in_progress && !headers_already_sent) {
597-
pending_actions.push_back(
598-
boost::bind(
599-
&async_connection<Tag,Handler>::continue_write<Range>
600-
, async_connection<Tag,Handler>::shared_from_this()
601-
, range, callback_function));
602-
return;
603-
}
604-
605580
// linearize the whole range into a vector
606581
// of fixed-sized buffers, then schedule an asynchronous
607582
// write of these buffers -- make sure they are live
@@ -648,25 +623,47 @@ namespace boost { namespace network { namespace http {
648623
}
649624

650625
if (!buffers->empty()) {
651-
boost::function<void(boost::system::error_code const &)> f = callback;
652-
asio::async_write(
653-
socket_
654-
, *buffers
655-
, strand.wrap(
656-
boost::bind(
657-
&async_connection<Tag,Handler>::handle_write
658-
, async_connection<Tag,Handler>::shared_from_this()
659-
, f
660-
, temporaries
661-
, buffers // keep these alive until the handler is called!
662-
, boost::asio::placeholders::error
663-
, boost::asio::placeholders::bytes_transferred
664-
)
665-
)
666-
);
626+
write_vec_impl(*buffers, callback, temporaries, buffers);
667627
}
668628
}
669629

630+
template <class ConstBufferSeq, class Callback>
631+
void write_vec_impl(ConstBufferSeq const & seq
632+
,Callback const & callback
633+
,shared_array_list temporaries
634+
,shared_buffers buffers)
635+
{
636+
lock_guard lock(headers_mutex);
637+
if (error_encountered)
638+
boost::throw_exception(boost::system::system_error(*error_encountered));
639+
640+
boost::function<void()> continuation = boost::bind(
641+
&async_connection<Tag,Handler>::write_vec_impl<ConstBufferSeq, Callback>
642+
,async_connection<Tag,Handler>::shared_from_this()
643+
,seq, callback, temporaries, buffers
644+
);
645+
646+
if (!headers_already_sent && !headers_in_progress) {
647+
write_headers_only(continuation);
648+
return;
649+
} else if (headers_in_progress && !headers_already_sent) {
650+
pending_actions.push_back(continuation);
651+
return;
652+
}
653+
654+
asio::async_write(
655+
socket_
656+
,seq
657+
,boost::bind(
658+
&async_connection<Tag,Handler>::handle_write
659+
,async_connection<Tag,Handler>::shared_from_this()
660+
,callback
661+
,temporaries
662+
,buffers
663+
,asio::placeholders::error
664+
,asio::placeholders::bytes_transferred)
665+
);
666+
}
670667
};
671668

672669
} /* http */

0 commit comments

Comments
 (0)