2 // Copyright (c) 2016-2019 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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_TEST_YIELD_TO_HPP
11 #define BOOST_BEAST_TEST_YIELD_TO_HPP
13 #include <boost/asio/executor_work_guard.hpp>
14 #include <boost/asio/io_context.hpp>
15 #include <boost/asio/spawn.hpp>
16 #include <condition_variable>
26 /** Mix-in to support tests using asio coroutines.
28 Derive from this class and use yield_to to launch test
29 functions inside coroutines. This is handy for testing
30 asynchronous asio code.
38 beast::detail::select_work_guard_t<
39 net::io_context::executor_type>
41 std::vector<std::thread> threads_;
43 std::condition_variable cv_;
44 std::size_t running_ = 0;
47 /// The type of yield context passed to functions.
52 enable_yield_to(std::size_t concurrency = 1)
53 : work_(beast::detail::make_work_guard(
56 threads_.reserve(concurrency);
58 threads_.emplace_back(
65 for(auto& t : threads_)
69 /// Return the `io_context` associated with the object
76 /** Run one or more functions, each in a coroutine.
78 This call will block until all coroutines terminate.
80 Each functions should have this signature:
82 void f(yield_context);
85 @param fn... One or more functions to invoke.
87 #if BOOST_BEAST_DOXYGEN
92 template<class F0, class... FN>
94 yield_to(F0&& f0, FN&&... fn);
103 template<class F0, class... FN>
105 spawn(F0&& f, FN&&... fn);
108 template<class F0, class... FN>
111 yield_to(F0&& f0, FN&&... fn)
113 running_ = 1 + sizeof...(FN);
115 std::unique_lock<std::mutex> lock{m_};
116 cv_.wait(lock, [&]{ return running_ == 0; });
119 template<class F0, class... FN>
123 spawn(F0&& f, FN&&... fn)
126 [&](yield_context yield)
129 std::lock_guard<std::mutex> lock{m_};
133 , boost::coroutines::attributes(2 * 1024 * 1024));