2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-10 23:32:28 +00:00
Files
fiber/examples/asio/yield.hpp
2015-09-01 17:17:38 +02:00

128 lines
4.0 KiB
C++

//
// yield.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// modified by Oliver Kowalke and Nat Goodspeed
//
#ifndef BOOST_FIBERS_ASIO_YIELD_HPP
#define BOOST_FIBERS_ASIO_YIELD_HPP
#include <memory> // std::allocator
#include <boost/config.hpp>
#include "promise_completion_token.hpp"
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace asio {
/// Class used to specify that a Boost.Asio asynchronous operation should
/// suspend the calling fiber until completion.
/**
* The yield_t class is used to indicate that a Boost.Asio asynchronous
* operation should suspend the calling fiber until its completion. The
* asynchronous function will either return a suitable value, or will throw an
* exception indicating the error. A yield_t object may be passed as a handler
* to an asynchronous operation, typically using the special value @c
* boost::fibers::asio::yield. For example:
*
* @code std::size_t length_read
* = my_socket.async_read_some(my_buffer, boost::fibers::asio::yield); @endcode
*
* The initiating function (async_read_some in the above example) does not
* return to the calling fiber until the asynchronous read has completed. Like
* its synchronous counterpart, it returns the result of the operation. If the
* operation completes with an error_code indicating failure, it is converted
* into a system_error and thrown as an exception.
*
* To suppress a possible error exception:
* @code
* boost::system::error_code ec;
* std::size_t length_read =
* my_socket.async_read_some(my_buffer, boost::fibers::asio::yield[ec]);
* // test ec for success
* @endcode
*
* The crucial distinction between
* @code
* std::size_t length_read = my_socket.read_some(my_buffer);
* @endcode
* and
* @code
* std::size_t length_read =
* my_socket.async_read_some(my_buffer, boost::fibers::asio::yield);
* @code
* is that <tt>read_some()</tt> blocks the entire calling @em thread, whereas
* <tt>async_read_some(..., boost::fibers::asio::yield)</tt> blocks only the
* calling @em fiber, permitting other fibers on the same thread to continue
* running.
*
* To specify an alternate allocator for the internal
* <tt>boost::fibers::promise</tt>:
* @code
* boost::fibers::asio::yield.with(alloc_instance)
* @endcode
*
* To bind a <tt>boost::system::error_code</tt> @a ec as well as using an
* alternate allocator:
* @code
* boost::fibers::asio::yield.with(alloc_instance)[ec]
* @endcode
*/
//[fibers_asio_yield_t
template< typename Allocator = std::allocator< void > >
class yield_t : public promise_completion_token< Allocator > {
public:
/// Construct with default-constructed allocator.
BOOST_CONSTEXPR yield_t() {
}
/*= // ... ways to use an alternate allocator or bind an error_code ...*/
/*=};*/
//]
/// Construct using specified allocator.
explicit yield_t( Allocator const& allocator) :
promise_completion_token< Allocator >( allocator) {
}
/// Specify an alternate allocator.
template< typename OtherAllocator >
yield_t< OtherAllocator > with( OtherAllocator const& allocator) const {
return yield_t< OtherAllocator >( allocator);
}
/// Bind an error_code to suppress error exception.
yield_t operator[]( boost::system::error_code & ec) const {
// Return a copy because typical usage will be on our canonical
// instance. Don't leave the canonical instance with a dangling
// binding to a transient error_code!
yield_t tmp;
tmp.ec_ = & ec;
return tmp;
}
};
//[fibers_asio_yield
/// A special value, similar to std::nothrow.
BOOST_CONSTEXPR_OR_CONST yield_t<> yield;
//]
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#include "detail/yield.hpp"
#endif // BOOST_FIBERS_ASIO_YIELD_HPP