From eecd73a23a123014d27f51700522b07d52fbab3a Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Sun, 17 Jan 2010 21:48:17 +0000 Subject: [PATCH] Document ordering of handlers in strands. Fix error in streambuf snippet. [SVN r59104] --- doc/reference.qbk | 92 +++++++++++++++++++++++++- include/boost/asio/basic_streambuf.hpp | 2 +- include/boost/asio/strand.hpp | 40 +++++++++++ 3 files changed, 131 insertions(+), 3 deletions(-) diff --git a/doc/reference.qbk b/doc/reference.qbk index d1b943c8..59fce702 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -30284,7 +30284,7 @@ Reading from a socket directly into a streambuf: boost::asio::streambuf b; // reserve 512 bytes in output sequence - boost::asio::streambuf::const_buffers_type bufs = b.prepare(512); + boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512); size_t n = sock.receive(bufs); @@ -37994,6 +37994,50 @@ Provides serialised handler execution. The [link boost_asio.reference.io_service__strand `io_service::strand`] class provides the ability to post and dispatch handlers with the guarantee that none of those handlers will execute concurrently. +[heading Order of handler invocation] + +Given: + + +* a strand object s + + +* an object a meeting completion handler requirements + + +* an object a1 which is an arbitrary copy of a made by the implementation + + +* an object b meeting completion handler requirements + + +* an object b1 which is an arbitrary copy of b made by the implementation + +if any of the following conditions are true: + + +* s.post(a) happens-before s.post(b) + + +* s.post(a) happens-before s.dispatch(b), where the latter is performed outside the strand + + +* s.dispatch(a) happens-before s.post(b), where the former is performed outside the strand + + +* s.dispatch(a) happens-before s.dispatch(b), where both are performed outside the strand + +then `asio_handler_invoke(a1, &a1)` happens-before `asio_handler_invoke(b1, &b1)`. + +Note that in the following case: + + async_op_1(..., s.wrap(a)); + async_op_2(..., s.wrap(b)); + + +the completion of the first async operation will perform `s.dispatch(a)`, and the second will perform `s.dispatch(b)`, but the order in which those are performed is unspecified. That is, you cannot state whether one happens-before the other. Therefore none of the above conditions are met and no ordering guarantee is made. + + [heading Thread Safety] [*Distinct] [*objects:] Safe. @@ -64243,6 +64287,50 @@ Typedef for backwards compatibility. The [link boost_asio.reference.io_service__strand `io_service::strand`] class provides the ability to post and dispatch handlers with the guarantee that none of those handlers will execute concurrently. +[heading Order of handler invocation] + +Given: + + +* a strand object s + + +* an object a meeting completion handler requirements + + +* an object a1 which is an arbitrary copy of a made by the implementation + + +* an object b meeting completion handler requirements + + +* an object b1 which is an arbitrary copy of b made by the implementation + +if any of the following conditions are true: + + +* s.post(a) happens-before s.post(b) + + +* s.post(a) happens-before s.dispatch(b), where the latter is performed outside the strand + + +* s.dispatch(a) happens-before s.post(b), where the former is performed outside the strand + + +* s.dispatch(a) happens-before s.dispatch(b), where both are performed outside the strand + +then `asio_handler_invoke(a1, &a1)` happens-before `asio_handler_invoke(b1, &b1)`. + +Note that in the following case: + + async_op_1(..., s.wrap(a)); + async_op_2(..., s.wrap(b)); + + +the completion of the first async operation will perform `s.dispatch(a)`, and the second will perform `s.dispatch(b)`, but the order in which those are performed is unspecified. That is, you cannot state whether one happens-before the other. Therefore none of the above conditions are met and no ordering guarantee is made. + + [heading Thread Safety] [*Distinct] [*objects:] Safe. @@ -65167,7 +65255,7 @@ Reading from a socket directly into a streambuf: boost::asio::streambuf b; // reserve 512 bytes in output sequence - boost::asio::streambuf::const_buffers_type bufs = b.prepare(512); + boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512); size_t n = sock.receive(bufs); diff --git a/include/boost/asio/basic_streambuf.hpp b/include/boost/asio/basic_streambuf.hpp index cf890d3f..e5f8a8dc 100644 --- a/include/boost/asio/basic_streambuf.hpp +++ b/include/boost/asio/basic_streambuf.hpp @@ -96,7 +96,7 @@ namespace asio { * boost::asio::streambuf b; * * // reserve 512 bytes in output sequence - * boost::asio::streambuf::const_buffers_type bufs = b.prepare(512); + * boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512); * * size_t n = sock.receive(bufs); * diff --git a/include/boost/asio/strand.hpp b/include/boost/asio/strand.hpp index c7c64a5e..a64d4867 100644 --- a/include/boost/asio/strand.hpp +++ b/include/boost/asio/strand.hpp @@ -30,6 +30,46 @@ namespace asio { * handlers with the guarantee that none of those handlers will execute * concurrently. * + * @par Order of handler invocation + * Given: + * + * @li a strand object @c s + * + * @li an object @c a meeting completion handler requirements + * + * @li an object @c a1 which is an arbitrary copy of @c a made by the + * implementation + * + * @li an object @c b meeting completion handler requirements + * + * @li an object @c b1 which is an arbitrary copy of @c b made by the + * implementation + * + * if any of the following conditions are true: + * + * @li @c s.post(a) happens-before @c s.post(b) + * + * @li @c s.post(a) happens-before @c s.dispatch(b), where the latter is + * performed outside the strand + * + * @li @c s.dispatch(a) happens-before @c s.post(b), where the former is + * performed outside the strand + * + * @li @c s.dispatch(a) happens-before @c s.dispatch(b), where both are + * performed outside the strand + * + * then @c asio_handler_invoke(a1, &a1) happens-before + * @c asio_handler_invoke(b1, &b1). + * + * Note that in the following case: + * @code async_op_1(..., s.wrap(a)); + * async_op_2(..., s.wrap(b)); @endcode + * the completion of the first async operation will perform @c s.dispatch(a), + * and the second will perform @c s.dispatch(b), but the order in which those + * are performed is unspecified. That is, you cannot state whether one + * happens-before the other. Therefore none of the above conditions are met and + * no ordering guarantee is made. + * * @par Thread Safety * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Safe.