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) : work_(boost::asio::make_work_guard(ios_))
44 {
45 threads_.reserve(concurrency);
46 while (concurrency--)
47 threads_.emplace_back([&] { ios_.run(); });
48 }
49
51 {
52 work_ = boost::none;
53 for (auto& t : threads_)
54 t.join();
55 }
56
58 boost::asio::io_context&
60 {
61 return ios_;
62 }
63
75#if BEAST_DOXYGEN
76 template <class... FN>
77 void
78 yield_to(FN&&... fn);
79#else
80 template <class F0, class... FN>
81 void
82 yield_to(F0&& f0, FN&&... fn);
83#endif
84
85private:
86 void
88 {
89 }
90
91 template <class F0, class... FN>
92 void
93 spawn(F0&& f, FN&&... fn);
94};
95
96template <class F0, class... FN>
97void
98enable_yield_to::yield_to(F0&& f0, FN&&... fn)
99{
100 running_ = 1 + sizeof...(FN);
101 spawn(f0, fn...);
103 cv_.wait(lock, [&] { return running_ == 0; });
104}
105
106template <class F0, class... FN>
107inline void
108enable_yield_to::spawn(F0&& f, FN&&... fn)
109{
110 boost::asio::spawn(
111 ios_,
112 boost::allocator_arg,
113 boost::context::fixedsize_stack(2 * 1024 * 1024),
114 [&](yield_context yield) {
115 f(yield);
116 std::lock_guard lock{m_};
117 if (--running_ == 0)
118 cv_.notify_all();
119 },
120 [](std::exception_ptr e) {
121 if (e)
123 });
124 spawn(fn...);
125}
126
127} // namespace test
128} // 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:59
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:98
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)