include/boost/capy/ex/frame_allocator.hpp

100.0% Lines (7/7) 100.0% Functions (3/3) -% Branches (0/0)
include/boost/capy/ex/frame_allocator.hpp
Line Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.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 // Official repository: https://github.com/cppalliance/capy
8 //
9
10 #ifndef BOOST_CAPY_FRAME_ALLOCATOR_HPP
11 #define BOOST_CAPY_FRAME_ALLOCATOR_HPP
12
13 #include <boost/capy/detail/config.hpp>
14
15 #include <memory_resource>
16
17 /* Design rationale (pdimov):
18
19 This accessor is a thin wrapper over a thread-local pointer.
20 It returns exactly what was stored, including nullptr. No
21 dynamic initializer on the thread-local; a dynamic TLS
22 initializer moves you into a costlier implementation bucket
23 on some platforms - avoid it.
24
25 Null handling is the caller's responsibility (e.g. in
26 promise_type::operator new). The accessor must not substitute
27 a default, because there are multiple valid choices
28 (new_delete_resource, the default pmr resource, etc.). If
29 the allocator is not set, it reports "not set" and the
30 caller interprets that however it wants.
31 */
32
33 namespace boost {
34 namespace capy {
35
36 namespace detail {
37
38 inline std::pmr::memory_resource*&
39 20850 current_frame_allocator_ref() noexcept
40 {
41 static thread_local std::pmr::memory_resource* mr = nullptr;
42 20850 return mr;
43 }
44
45 } // namespace detail
46
47 /** Return the current frame allocator for this thread.
48
49 These accessors exist to implement the allocator
50 propagation portion of the @ref IoAwaitable protocol.
51 Launch functions (`run_async`, `run`) set the
52 thread-local value before invoking a child coroutine;
53 the child's `promise_type::operator new` reads it to
54 allocate the coroutine frame from the correct resource.
55
56 The value is only valid during a narrow execution
57 window. Between a coroutine's resumption
58 and the next suspension point, the protocol guarantees
59 that TLS contains the allocator associated with the
60 currently running chain. Outside that window the value
61 is indeterminate. Only code that implements an
62 @ref IoAwaitable should call these functions.
63
64 A return value of `nullptr` means "not specified" -
65 no allocator has been established for this chain.
66 The awaitable is free to use whatever allocation
67 strategy makes best sense (e.g.
68 `std::pmr::new_delete_resource()`).
69
70 Use of the frame allocator is optional. An awaitable
71 that does not consult this value to allocate its
72 coroutine frame is never wrong. However, a conforming
73 awaitable must still propagate the allocator faithfully
74 so that downstream coroutines can use it.
75
76 @return The thread-local memory_resource pointer,
77 or `nullptr` if none has been set.
78
79 @see set_current_frame_allocator, IoAwaitable
80 */
81 inline
82 std::pmr::memory_resource*
83 5780 get_current_frame_allocator() noexcept
84 {
85 5780 return detail::current_frame_allocator_ref();
86 }
87
88 /** Set the current frame allocator for this thread.
89
90 Installs @p mr as the frame allocator that will be
91 read by the next coroutine's `promise_type::operator
92 new` on this thread. Only launch functions and
93 @ref IoAwaitable machinery should call this; see
94 @ref get_current_frame_allocator for the full protocol
95 description.
96
97 Passing `nullptr` means "not specified" - no
98 particular allocator is established for the chain.
99
100 @param mr The memory_resource to install, or
101 `nullptr` to clear.
102
103 @see get_current_frame_allocator, IoAwaitable
104 */
105 inline void
106 15070 set_current_frame_allocator(
107 std::pmr::memory_resource* mr) noexcept
108 {
109 15070 detail::current_frame_allocator_ref() = mr;
110 15070 }
111
112 } // namespace capy
113 } // namespace boost
114
115 #endif
116