2 // Copyright (c) 2016-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)
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/io_context.hpp>
14 #include <boost/asio/spawn.hpp>
15 #include <boost/optional.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.
35 boost::asio::io_context ioc_;
39 boost::asio::executor_work_guard<
40 boost::asio::io_context::executor_type>> work_;
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.
49 boost::asio::yield_context;
52 enable_yield_to(std::size_t concurrency = 1)
53 : work_(ioc_.get_executor())
55 threads_.reserve(concurrency);
57 threads_.emplace_back(
64 for(auto& t : threads_)
68 /// Return the `io_context` associated with the object
69 boost::asio::io_context&
75 /** Run one or more functions, each in a coroutine.
77 This call will block until all coroutines terminate.
79 Each functions should have this signature:
81 void f(yield_context);
84 @param fn... One or more functions to invoke.
86 #if BOOST_BEAST_DOXYGEN
91 template<class F0, class... FN>
93 yield_to(F0&& f0, FN&&... fn);
102 template<class F0, class... FN>
104 spawn(F0&& f, FN&&... fn);
107 template<class F0, class... FN>
110 yield_to(F0&& f0, FN&&... fn)
112 running_ = 1 + sizeof...(FN);
114 std::unique_lock<std::mutex> lock{m_};
115 cv_.wait(lock, [&]{ return running_ == 0; });
118 template<class F0, class... FN>
122 spawn(F0&& f, FN&&... fn)
124 boost::asio::spawn(ioc_,
125 [&](yield_context yield)
128 std::lock_guard<std::mutex> lock{m_};
132 , boost::coroutines::attributes(2 * 1024 * 1024));