xrpld
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 <cstddef>
15#include <exception>
16#include <mutex>
17#include <thread>
18#include <vector>
19
20namespace beast::test {
21
30{
31protected:
32 boost::asio::io_context ios_;
33
34private:
35 boost::optional<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>> work_;
40
41public:
45 using yield_context = boost::asio::yield_context;
46
47 explicit EnableYieldTo(std::size_t concurrency = 1) : work_(boost::asio::make_work_guard(ios_))
48 {
49 threads_.reserve(concurrency);
50 for (std::size_t i = 0; i < concurrency; ++i)
51 {
52 threads_.emplace_back([&] { ios_.run(); });
53 }
54 }
55
57 {
58 work_ = boost::none;
59 for (auto& t : threads_)
60 t.join();
61 }
62
66 boost::asio::io_context&
68 {
69 return ios_;
70 }
71
84#if BEAST_DOXYGEN
85 template <class... FN>
86 void
87 yield_to(FN&&... fn);
88#else
89 template <class F0, class... FN>
90 void
91 yieldTo(F0&& f0, FN&&... fn);
92#endif
93
94private:
95 void
97 {
98 }
99
100 template <class F0, class... FN>
101 void
102 spawn(F0&& f, FN&&... fn);
103};
104
105template <class F0, class... FN>
106void
107EnableYieldTo::yieldTo(F0&& f0, FN&&... fn)
108{
109 running_ = 1 + sizeof...(FN);
110 spawn(f0, fn...);
112 cv_.wait(lock, [&] { return running_ == 0; });
113}
114
115template <class F0, class... FN>
116inline void
117EnableYieldTo::spawn(F0&& f, FN&&... fn)
118{
119 boost::asio::spawn(
120 ios_,
121 boost::allocator_arg,
122 boost::context::fixedsize_stack(2 * 1024 * 1024),
123 [&](yield_context yield) {
124 f(yield);
125 std::scoped_lock const lock{m_};
126 if (--running_ == 0)
127 cv_.notify_all();
128 },
129 [](std::exception_ptr e) {
130 if (e)
132 });
133 spawn(fn...);
134}
135
136} // namespace beast::test
EnableYieldTo(std::size_t concurrency=1)
Definition yield_to.h:47
std::condition_variable cv_
Definition yield_to.h:38
std::vector< std::thread > threads_
Definition yield_to.h:36
boost::asio::io_context ios_
Definition yield_to.h:32
boost::asio::io_context & getIoContext()
Return the io_context associated with the object.
Definition yield_to.h:67
boost::asio::yield_context yield_context
The type of yield context passed to functions.
Definition yield_to.h:45
boost::optional< boost::asio::executor_work_guard< boost::asio::io_context::executor_type > > work_
Definition yield_to.h:35
void yieldTo(F0 &&f0, FN &&... fn)
Run one or more functions, each in a coroutine.
Definition yield_to.h:107
T rethrow_exception(T... args)