Skip to content

Commit 63c6510

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 3b28e1e commit 63c6510

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
@@ -212,10 +212,15 @@ namespace boost { namespace network { namespace http {
212212
void write(Range const & range, Callback const & callback) {
213213
lock_guard lock(headers_mutex);
214214
if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered));
215-
boost::function<void(boost::system::error_code)> f = callback;
216215
write_impl(boost::make_iterator_range(range), callback);
217216
}
218217

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

@@ -510,15 +515,6 @@ namespace boost { namespace network { namespace http {
510515

511516
void do_nothing() {}
512517

513-
template <class Range>
514-
void continue_write(Range range, boost::function<void(boost::system::error_code)> callback) {
515-
thread_pool().post(
516-
boost::bind(
517-
&async_connection<Tag,Handler>::write_impl<Range>
518-
, async_connection<Tag,Handler>::shared_from_this()
519-
, range, callback));
520-
}
521-
522518
template <class Callback>
523519
void write_first_line(Callback callback) {
524520
lock_guard lock(headers_mutex);
@@ -603,27 +599,6 @@ namespace boost { namespace network { namespace http {
603599

604600
template <class Range>
605601
void write_impl(Range range, boost::function<void(boost::system::error_code)> callback) {
606-
lock_guard lock(headers_mutex);
607-
boost::function<void(boost::system::error_code)> callback_function =
608-
callback;
609-
610-
if (!headers_already_sent && !headers_in_progress) {
611-
write_headers_only(
612-
boost::bind(
613-
&async_connection<Tag,Handler>::continue_write<Range>
614-
, async_connection<Tag,Handler>::shared_from_this()
615-
, range, callback_function
616-
));
617-
return;
618-
} else if (headers_in_progress && !headers_already_sent) {
619-
pending_actions.push_back(
620-
boost::bind(
621-
&async_connection<Tag,Handler>::continue_write<Range>
622-
, async_connection<Tag,Handler>::shared_from_this()
623-
, range, callback_function));
624-
return;
625-
}
626-
627602
// linearize the whole range into a vector
628603
// of fixed-sized buffers, then schedule an asynchronous
629604
// write of these buffers -- make sure they are live
@@ -670,25 +645,47 @@ namespace boost { namespace network { namespace http {
670645
}
671646

672647
if (!buffers->empty()) {
673-
boost::function<void(boost::system::error_code const &)> f = callback;
674-
asio::async_write(
675-
socket_
676-
, *buffers
677-
, strand.wrap(
678-
boost::bind(
679-
&async_connection<Tag,Handler>::handle_write
680-
, async_connection<Tag,Handler>::shared_from_this()
681-
, f
682-
, temporaries
683-
, buffers // keep these alive until the handler is called!
684-
, boost::asio::placeholders::error
685-
, boost::asio::placeholders::bytes_transferred
686-
)
687-
)
688-
);
648+
write_vec_impl(*buffers, callback, temporaries, buffers);
689649
}
690650
}
691651

652+
template <class ConstBufferSeq, class Callback>
653+
void write_vec_impl(ConstBufferSeq const & seq
654+
,Callback const & callback
655+
,shared_array_list temporaries
656+
,shared_buffers buffers)
657+
{
658+
lock_guard lock(headers_mutex);
659+
if (error_encountered)
660+
boost::throw_exception(boost::system::system_error(*error_encountered));
661+
662+
boost::function<void()> continuation = boost::bind(
663+
&async_connection<Tag,Handler>::write_vec_impl<ConstBufferSeq, Callback>
664+
,async_connection<Tag,Handler>::shared_from_this()
665+
,seq, callback, temporaries, buffers
666+
);
667+
668+
if (!headers_already_sent && !headers_in_progress) {
669+
write_headers_only(continuation);
670+
return;
671+
} else if (headers_in_progress && !headers_already_sent) {
672+
pending_actions.push_back(continuation);
673+
return;
674+
}
675+
676+
asio::async_write(
677+
socket_
678+
,seq
679+
,boost::bind(
680+
&async_connection<Tag,Handler>::handle_write
681+
,async_connection<Tag,Handler>::shared_from_this()
682+
,callback
683+
,temporaries
684+
,buffers
685+
,asio::placeholders::error
686+
,asio::placeholders::bytes_transferred)
687+
);
688+
}
692689
};
693690

694691
} /* http */

0 commit comments

Comments
 (0)