libs/corosio/src/corosio/src/detail/cached_initiator.hpp

96.2% Lines (25/26) 90.0% Functions (18/20) 100.0% Branches (11/11)
libs/corosio/src/corosio/src/detail/cached_initiator.hpp
Line Branch Hits Source Code
1 //
2 // Copyright (c) 2024 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_DETAIL_CACHED_INITIATOR_HPP
11 #define BOOST_COROSIO_DETAIL_CACHED_INITIATOR_HPP
12
13 #include <coroutine>
14 #include <cstddef>
15
16 namespace boost::corosio::detail {
17
18 /** Cached initiator coroutine frame with RAII cleanup.
19
20 Manages the lifecycle of a cached coroutine frame used for I/O
21 initiator coroutines. Automatically destroys the coroutine handle
22 and frees the cached frame memory on destruction.
23 */
24 struct cached_initiator
25 {
26 void* frame = nullptr;
27 std::coroutine_handle<> handle;
28
29 10258 ~cached_initiator()
30 {
31
2/2
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 10180 times.
10258 if (handle)
32 78 handle.destroy();
33
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 10180 times.
10258 if (frame)
34 78 ::operator delete(frame);
35 10258 }
36
37 10258 cached_initiator() = default;
38 cached_initiator(cached_initiator const&) = delete;
39 cached_initiator& operator=(cached_initiator const&) = delete;
40
41 /** Start initiator coroutine that calls Fn on impl.
42
43 Destroys any existing coroutine, creates a new initiator that
44 will call the specified member function, and returns the handle
45 for symmetric transfer.
46
47 @tparam Fn Member function pointer to call (e.g., &Impl::do_read_io)
48 @param impl Pointer to the I/O object implementation
49 @return Coroutine handle for symmetric transfer
50 */
51 template<auto Fn, class Impl>
52 157693 std::coroutine_handle<> start(Impl* impl)
53 {
54
2/2
✓ Branch 1 taken 157615 times.
✓ Branch 2 taken 78 times.
157693 if (handle)
55
1/1
✓ Branch 1 taken 157615 times.
157615 handle.destroy();
56
1/1
✓ Branch 1 taken 157693 times.
157693 auto initiator = make_initiator_coro<Fn>(frame, impl);
57 157693 handle = initiator.h;
58 315386 return initiator.h;
59 }
60
61 private:
62 template<class Impl, auto Fn>
63 struct initiator_coro
64 {
65 struct promise_type
66 {
67 Impl* impl;
68
69 157693 static void* operator new(std::size_t n, void*& cached, Impl*)
70 {
71
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 157615 times.
157693 if (!cached)
72 78 cached = ::operator new(n);
73 157693 return cached;
74 }
75
76 157693 static void operator delete(void*) noexcept {}
77
78 157693 std::suspend_always initial_suspend() noexcept { return {}; }
79 157693 std::suspend_always final_suspend() noexcept { return {}; }
80
81 157693 initiator_coro get_return_object()
82 {
83 157693 return {std::coroutine_handle<promise_type>::from_promise(*this)};
84 }
85
86 157693 void return_void() {}
87 void unhandled_exception() { std::terminate(); }
88 };
89
90 using handle_type = std::coroutine_handle<promise_type>;
91 handle_type h;
92 };
93
94 template<auto Fn, class Impl>
95
1/1
✓ Branch 1 taken 157693 times.
157693 static initiator_coro<Impl, Fn> make_initiator_coro(void*&, Impl* impl)
96 {
97 (impl->*Fn)();
98 co_return;
99 315386 }
100 };
101
102 } // namespace boost::corosio::detail
103
104 #endif
105