]> git.proxmox.com Git - ceph.git/blame - ceph/src/Beast/extras/beast/test/yield_to.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / extras / beast / test / yield_to.hpp
CommitLineData
7c673cae
FG
1//
2// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
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)
6//
7
8#ifndef BEAST_TEST_YIELD_TO_HPP
9#define BEAST_TEST_YIELD_TO_HPP
10
11#include <boost/asio/io_service.hpp>
12#include <boost/asio/spawn.hpp>
13#include <boost/optional.hpp>
14#include <condition_variable>
15#include <functional>
16#include <mutex>
17#include <thread>
18
19namespace beast {
20namespace test {
21
22/** Mix-in to support tests using asio coroutines.
23
24 Derive from this class and use yield_to to launch test
25 functions inside coroutines. This is handy for testing
26 asynchronous asio code.
27*/
28class enable_yield_to
29{
30protected:
31 boost::asio::io_service ios_;
32
33private:
34 boost::optional<boost::asio::io_service::work> work_;
35 std::thread thread_;
36 std::mutex m_;
37 std::condition_variable cv_;
38 bool running_ = false;
39
40public:
41 /// The type of yield context passed to functions.
42 using yield_context =
43 boost::asio::yield_context;
44
45 enable_yield_to()
46 : work_(ios_)
47 , thread_([&]
48 {
49 ios_.run();
50 }
51 )
52 {
53 }
54
55 ~enable_yield_to()
56 {
57 work_ = boost::none;
58 thread_.join();
59 }
60
61 /// Return the `io_service` associated with the object
62 boost::asio::io_service&
63 get_io_service()
64 {
65 return ios_;
66 }
67
68 /** Run a function in a coroutine.
69
70 This call will block until the coroutine terminates.
71
72 Function will be called with this signature:
73
74 @code
75 void f(args..., yield_context);
76 @endcode
77
78 @param f The Callable object to invoke.
79
80 @param args Optional arguments forwarded to the callable object.
81 */
82#if BEAST_DOXYGEN
83 template<class F, class... Args>
84 void
85 yield_to(F&& f, Args&&... args);
86#else
87 template<class F>
88 void
89 yield_to(F&& f);
90
91 template<class Function, class Arg, class... Args>
92 void
93 yield_to(Function&& f, Arg&& arg, Args&&... args)
94 {
95 yield_to(std::bind(f,
96 std::forward<Arg>(arg),
97 std::forward<Args>(args)...,
98 std::placeholders::_1));
99 }
100#endif
101};
102
103template<class Function>
104void
105enable_yield_to::yield_to(Function&& f)
106{
107 {
108 std::lock_guard<std::mutex> lock(m_);
109 running_ = true;
110 }
111 boost::asio::spawn(ios_,
112 [&](boost::asio::yield_context do_yield)
113 {
114 f(do_yield);
115 std::lock_guard<std::mutex> lock(m_);
116 running_ = false;
117 cv_.notify_all();
118 }
119 , boost::coroutines::attributes(2 * 1024 * 1024));
120
121 std::unique_lock<std::mutex> lock(m_);
122 cv_.wait(lock, [&]{ return ! running_; });
123}
124
125} // test
126} // beast
127
128#endif