]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/handler_ptr.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / core / handler_ptr.hpp
1 //
2 // Copyright (c) 2016-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 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_HANDLER_PTR_HPP
11 #define BOOST_BEAST_HANDLER_PTR_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/detail/type_traits.hpp>
15 #include <atomic>
16 #include <cstdint>
17 #include <type_traits>
18 #include <utility>
19
20 namespace boost {
21 namespace beast {
22
23 /** A smart pointer container with associated completion handler.
24
25 This is a smart pointer that retains shared ownership of an
26 object through a pointer. Memory is managed using the allocation
27 and deallocation functions associated with a completion handler,
28 which is also stored in the object. The managed object is
29 destroyed and its memory deallocated when one of the following
30 happens:
31
32 @li The function @ref invoke is called.
33
34 @li The function @ref release_handler is called.
35
36 @li The last remaining container owning the object is destroyed.
37
38 Objects of this type are used in the implementation of
39 composed operations. Typically the composed operation's shared
40 state is managed by the @ref handler_ptr and an allocator
41 associated with the final handler is used to create the managed
42 object.
43
44 @note The reference count is stored using a 16 bit unsigned
45 integer. Making more than 2^16 copies of one object results
46 in undefined behavior.
47
48 @tparam T The type of the owned object.
49
50 @tparam Handler The type of the completion handler.
51 */
52 template<class T, class Handler>
53 class handler_ptr
54 {
55 struct P
56 {
57 T* t;
58 std::atomic<std::uint16_t> n;
59
60 // There's no way to put the handler anywhere else
61 // without exposing ourselves to race conditions
62 // and all sorts of ugliness.
63 // See:
64 // https://github.com/boostorg/beast/issues/215
65 Handler handler;
66
67 template<class DeducedHandler, class... Args>
68 P(DeducedHandler&& handler, Args&&... args);
69 };
70
71 P* p_;
72
73 public:
74 /// The type of element this object stores
75 using element_type = T;
76
77 /// The type of handler this object stores
78 using handler_type = Handler;
79
80 /// Copy assignment (disallowed).
81 handler_ptr& operator=(handler_ptr const&) = delete;
82
83 /** Destructs the owned object if no more @ref handler_ptr link to it.
84
85 If `*this` owns an object and it is the last @ref handler_ptr
86 owning it, the object is destroyed and the memory deallocated
87 using the associated deallocator.
88 */
89 ~handler_ptr();
90
91 /** Move constructor.
92
93 When this call returns, the moved-from container
94 will have no owned object.
95 */
96 handler_ptr(handler_ptr&& other);
97
98 /// Copy constructor
99 handler_ptr(handler_ptr const& other);
100
101 /** Construct a new @ref handler_ptr
102
103 This creates a new @ref handler_ptr with an owned object
104 of type `T`. The allocator associated with the handler will
105 be used to allocate memory for the owned object. The constructor
106 for the owned object will be called thusly:
107
108 @code
109 T(handler, std::forward<Args>(args)...)
110 @endcode
111
112 @param handler The handler to associate with the owned
113 object. The argument will be moved.
114
115 @param args Optional arguments forwarded to
116 the owned object's constructor.
117 */
118 template<class... Args>
119 handler_ptr(Handler&& handler, Args&&... args);
120
121 /** Construct a new @ref handler_ptr
122
123 This creates a new @ref handler_ptr with an owned object
124 of type `T`. The allocator associated with the handler will
125 be used to allocate memory for the owned object. The constructor
126 for the owned object will be called thusly:
127
128 @code
129 T(handler, std::forward<Args>(args)...)
130 @endcode
131
132 @param handler The handler to associate with the owned
133 object. The argument will be copied.
134
135 @param args Optional arguments forwarded to
136 the owned object's constructor.
137 */
138 template<class... Args>
139 handler_ptr(Handler const& handler, Args&&... args);
140
141 /// Returns a reference to the handler
142 handler_type&
143 handler() const
144 {
145 return p_->handler;
146 }
147
148 /// Returns `true` if `*this` owns an object.
149 explicit
150 operator bool() const
151 {
152 return p_ && p_->t;
153 }
154
155 /** Returns a pointer to the owned object.
156
157 If `*this` owns an object, a pointer to the
158 object is returned, else `nullptr` is returned.
159 */
160 T*
161 get() const
162 {
163 return p_ ? p_->t : nullptr;
164 }
165
166 /// Return a reference to the owned object.
167 T&
168 operator*() const
169 {
170 return *p_->t;
171 }
172
173 /// Return a pointer to the owned object.
174 T*
175 operator->() const
176 {
177 return p_->t;
178 }
179
180 /** Release ownership of the handler
181
182 If `*this` owns an object, it is first destroyed.
183
184 @return The released handler.
185 */
186 handler_type
187 release_handler();
188
189 /** Invoke the handler in the owned object.
190
191 This function invokes the handler in the owned object
192 with a forwarded argument list. Before the invocation,
193 the owned object is destroyed, satisfying the
194 deallocation-before-invocation Asio guarantee. All
195 instances of @ref handler_ptr which refer to the
196 same owned object will be reset, including this instance.
197
198 @note Care must be taken when the arguments are themselves
199 stored in the owned object. Such arguments must first be
200 moved to the stack or elsewhere, and then passed, or else
201 undefined behavior will result.
202 */
203 template<class... Args>
204 void
205 invoke(Args&&... args);
206 };
207
208 } // beast
209 } // boost
210
211 #include <boost/beast/core/impl/handler_ptr.ipp>
212
213 #endif