2 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BEAST_TEST_YIELD_TO_HPP
9 #define BEAST_TEST_YIELD_TO_HPP
11 #include <boost/asio/io_service.hpp>
12 #include <boost/asio/spawn.hpp>
13 #include <boost/optional.hpp>
14 #include <condition_variable>
22 /** Mix-in to support tests using asio coroutines.
24 Derive from this class and use yield_to to launch test
25 functions inside coroutines. This is handy for testing
26 asynchronous asio code.
31 boost::asio::io_service ios_;
34 boost::optional<boost::asio::io_service::work> work_;
37 std::condition_variable cv_;
38 bool running_ = false;
41 /// The type of yield context passed to functions.
43 boost::asio::yield_context;
61 /// Return the `io_service` associated with the object
62 boost::asio::io_service&
68 /** Run a function in a coroutine.
70 This call will block until the coroutine terminates.
72 Function will be called with this signature:
75 void f(args..., yield_context);
78 @param f The Callable object to invoke.
80 @param args Optional arguments forwarded to the callable object.
83 template<class F, class... Args>
85 yield_to(F&& f, Args&&... args);
91 template<class Function, class Arg, class... Args>
93 yield_to(Function&& f, Arg&& arg, Args&&... args)
96 std::forward<Arg>(arg),
97 std::forward<Args>(args)...,
98 std::placeholders::_1));
103 template<class Function>
105 enable_yield_to::yield_to(Function&& f)
108 std::lock_guard<std::mutex> lock(m_);
111 boost::asio::spawn(ios_,
112 [&](boost::asio::yield_context do_yield)
115 std::lock_guard<std::mutex> lock(m_);
119 , boost::coroutines::attributes(2 * 1024 * 1024));
121 std::unique_lock<std::mutex> lock(m_);
122 cv_.wait(lock, [&]{ return ! running_; });