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