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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy