rippled
Loading...
Searching...
No Matches
yield_to.h
1// Distributed under the Boost Software License, Version 1.0. (See accompanying
2// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3//
4
5#pragma once
6
7#include <boost/asio/executor_work_guard.hpp>
8#include <boost/asio/io_context.hpp>
9#include <boost/asio/spawn.hpp>
10#include <boost/optional.hpp>
11#include <boost/thread/csbl/memory/allocator_arg.hpp>
12
13#include <condition_variable>
14#include <mutex>
15#include <thread>
16#include <vector>
17
18namespace beast {
19namespace test {
20
28{
29protected:
30 boost::asio::io_context ios_;
31
32private:
33 boost::optional<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>> work_;
38
39public:
41 using yield_context = boost::asio::yield_context;
42
43 explicit enable_yield_to(std::size_t concurrency = 1)
44 : work_(boost::asio::make_work_guard(ios_))
45 {
46 threads_.reserve(concurrency);
47 while (concurrency--)
48 threads_.emplace_back([&] { ios_.run(); });
49 }
50
52 {
53 work_ = boost::none;
54 for (auto& t : threads_)
55 t.join();
56 }
57
59 boost::asio::io_context&
61 {
62 return ios_;
63 }
64
76#if BEAST_DOXYGEN
77 template <class... FN>
78 void
79 yield_to(FN&&... fn);
80#else
81 template <class F0, class... FN>
82 void
83 yield_to(F0&& f0, FN&&... fn);
84#endif
85
86private:
87 void
89 {
90 }
91
92 template <class F0, class... FN>
93 void
94 spawn(F0&& f, FN&&... fn);
95};
96
97template <class F0, class... FN>
98void
99enable_yield_to::yield_to(F0&& f0, FN&&... fn)
100{
101 running_ = 1 + sizeof...(FN);
102 spawn(f0, fn...);
104 cv_.wait(lock, [&] { return running_ == 0; });
105}
106
107template <class F0, class... FN>
108inline void
109enable_yield_to::spawn(F0&& f, FN&&... fn)
110{
111 boost::asio::spawn(
112 ios_,
113 boost::allocator_arg,
114 boost::context::fixedsize_stack(2 * 1024 * 1024),
115 [&](yield_context yield) {
116 f(yield);
117 std::lock_guard const lock{m_};
118 if (--running_ == 0)
119 cv_.notify_all();
120 },
121 [](std::exception_ptr e) {
122 if (e)
124 });
125 spawn(fn...);
126}
127
128} // namespace test
129} // namespace beast
Mix-in to support tests using asio coroutines.
Definition yield_to.h:28
boost::asio::io_context & get_io_context()
Return the io_context associated with the object.
Definition yield_to.h:60
enable_yield_to(std::size_t concurrency=1)
Definition yield_to.h:43
boost::asio::yield_context yield_context
The type of yield context passed to functions.
Definition yield_to.h:41
std::condition_variable cv_
Definition yield_to.h:36
void yield_to(F0 &&f0, FN &&... fn)
Run one or more functions, each in a coroutine.
Definition yield_to.h:99
boost::optional< boost::asio::executor_work_guard< boost::asio::io_context::executor_type > > work_
Definition yield_to.h:33
boost::asio::io_context ios_
Definition yield_to.h:30
std::vector< std::thread > threads_
Definition yield_to.h:34
T emplace_back(T... args)
T reserve(T... args)
T rethrow_exception(T... args)