Me No Dev 04963009ee
Update IDF to a0468b2 (#2108)
* Update IDF to a0468b2

* add missing ld file

* Fix PIO builds and change coex policy
2018-11-26 23:22:11 +01:00

227 lines
6.1 KiB
C++

//
// experimental/co_spawn.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 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)
//
#ifndef ASIO_EXPERIMENTAL_CO_SPAWN_HPP
#define ASIO_EXPERIMENTAL_CO_SPAWN_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
#include <experimental/coroutine>
#include "asio/executor.hpp"
#include "asio/strand.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace experimental {
namespace detail {
using std::experimental::coroutine_handle;
template <typename> class awaiter;
template <typename> class awaitee_base;
template <typename, typename> class awaitee;
template <typename, typename> class await_handler_base;
template <typename Executor, typename F, typename CompletionToken>
auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token);
} // namespace detail
namespace this_coro {
/// Awaitable type that returns a completion token for the current coroutine.
struct token_t {};
/// Awaitable object that returns a completion token for the current coroutine.
constexpr inline token_t token() { return {}; }
/// Awaitable type that returns the executor of the current coroutine.
struct executor_t {};
/// Awaitable object that returns the executor of the current coroutine.
constexpr inline executor_t executor() { return {}; }
} // namespace this_coro
/// A completion token that represents the currently executing coroutine.
/**
* The await_token class is used to represent the currently executing
* coroutine. An await_token may be passed as a handler to an asynchronous
* operation. For example:
*
* @code awaitable<void> my_coroutine()
* {
* await_token token = co_await this_coro::token();
* ...
* std::size_t n = co_await my_socket.async_read_some(buffer, token);
* ...
* } @endcode
*
* The initiating function (async_read_some in the above example) suspends the
* current coroutine. The coroutine is resumed when the asynchronous operation
* completes, and the result of the operation is returned.
*/
template <typename Executor>
class await_token
{
public:
/// The associated executor type.
typedef Executor executor_type;
/// Copy constructor.
await_token(const await_token& other) noexcept
: awaiter_(other.awaiter_)
{
}
/// Move constructor.
await_token(await_token&& other) noexcept
: awaiter_(std::exchange(other.awaiter_, nullptr))
{
}
/// Get the associated executor.
executor_type get_executor() const noexcept
{
return awaiter_->get_executor();
}
private:
// No assignment allowed.
await_token& operator=(const await_token&) = delete;
template <typename> friend class detail::awaitee_base;
template <typename, typename> friend class detail::await_handler_base;
// Private constructor used by awaitee_base.
explicit await_token(detail::awaiter<Executor>* a)
: awaiter_(a)
{
}
detail::awaiter<Executor>* awaiter_;
};
/// The return type of a coroutine or asynchronous operation.
template <typename T, typename Executor = strand<executor>>
class awaitable
{
public:
/// The type of the awaited value.
typedef T value_type;
/// The executor type that will be used for the coroutine.
typedef Executor executor_type;
/// Move constructor.
awaitable(awaitable&& other) noexcept
: awaitee_(std::exchange(other.awaitee_, nullptr))
{
}
/// Destructor
~awaitable()
{
if (awaitee_)
{
detail::coroutine_handle<
detail::awaitee<T, Executor>>::from_promise(
*awaitee_).destroy();
}
}
#if !defined(GENERATING_DOCUMENTATION)
// Support for co_await keyword.
bool await_ready() const noexcept
{
return awaitee_->ready();
}
// Support for co_await keyword.
void await_suspend(detail::coroutine_handle<detail::awaiter<Executor>> h)
{
awaitee_->attach_caller(h);
}
// Support for co_await keyword.
template <class U>
void await_suspend(detail::coroutine_handle<detail::awaitee<U, Executor>> h)
{
awaitee_->attach_caller(h);
}
// Support for co_await keyword.
T await_resume()
{
return awaitee_->get();
}
#endif // !defined(GENERATING_DOCUMENTATION)
private:
template <typename, typename> friend class detail::awaitee;
template <typename, typename> friend class detail::await_handler_base;
// Not copy constructible or copy assignable.
awaitable(const awaitable&) = delete;
awaitable& operator=(const awaitable&) = delete;
// Construct the awaitable from a coroutine's promise object.
explicit awaitable(detail::awaitee<T, Executor>* a) : awaitee_(a) {}
detail::awaitee<T, Executor>* awaitee_;
};
/// Spawn a new thread of execution.
template <typename Executor, typename F, typename CompletionToken,
typename = typename enable_if<is_executor<Executor>::value>::type>
inline auto co_spawn(const Executor& ex, F&& f, CompletionToken&& token)
{
return detail::co_spawn(ex, std::forward<F>(f),
std::forward<CompletionToken>(token));
}
/// Spawn a new thread of execution.
template <typename ExecutionContext, typename F, typename CompletionToken,
typename = typename enable_if<
is_convertible<ExecutionContext&, execution_context&>::value>::type>
inline auto co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token)
{
return detail::co_spawn(ctx.get_executor(), std::forward<F>(f),
std::forward<CompletionToken>(token));
}
/// Spawn a new thread of execution.
template <typename Executor, typename F, typename CompletionToken>
inline auto co_spawn(const await_token<Executor>& parent,
F&& f, CompletionToken&& token)
{
return detail::co_spawn(parent.get_executor(), std::forward<F>(f),
std::forward<CompletionToken>(token));
}
} // namespace experimental
} // namespace asio
#include "asio/detail/pop_options.hpp"
#include "asio/experimental/impl/co_spawn.hpp"
#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)
#endif // ASIO_EXPERIMENTAL_CO_SPAWN_HPP