Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / msg / async / dpdk / shared_ptr.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 /*
3  * This file is open source software, licensed to you under the terms
4  * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
5  * distributed with this work for additional information regarding copyright
6  * ownership.  You may not use this file except in compliance with the License.
7  *
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 /*
20  * Copyright (C) 2014 Cloudius Systems, Ltd.
21  */
22
23 #ifndef CEPH_LW_SHARED_PTR_H_
24 #define CEPH_LW_SHARED_PTR_H_
25
26 #include <utility>
27 #include <type_traits>
28 #include <functional>
29 #include <iostream>
30
31 // This header defines two shared pointer facilities, lw_shared_ptr<>
32 // modeled after std::shared_ptr<>.
33 //
34 // Unlike std::shared_ptr<>, neither of these implementations are thread
35 // safe, and two pointers sharing the same object must not be used in
36 // different threads.
37 //
38 // lw_shared_ptr<> is the more lightweight variant, with a lw_shared_ptr<>
39 // occupying just one machine word, and adding just one word to the shared
40 // object.  However, it does not support polymorphism.
41 //
42 // Both variants support shared_from_this() via enable_shared_from_this<>
43 // and lw_enable_shared_from_this<>().
44 //
45
46 template< class T >
47 using remove_const_t = typename remove_const<T>::type;
48
49 template <typename T>
50 class lw_shared_ptr;
51
52 template <typename T, typename... A>
53 lw_shared_ptr<T> make_lw_shared(A&&... a);
54
55 template <typename T>
56 lw_shared_ptr<T> make_lw_shared(T&& a);
57
58 template <typename T>
59 lw_shared_ptr<T> make_lw_shared(T& a);
60
61 // CRTP from this to enable shared_from_this:
62 template <typename T>
63 class enable_lw_shared_from_this {
64   long _count = 0;
65   using ctor = T;
66   T* to_value() { return static_cast<T*>(this); }
67   T* to_internal_object() { return static_cast<T*>(this); }
68  protected:
69   enable_lw_shared_from_this() noexcept {}
70   enable_lw_shared_from_this(enable_lw_shared_from_this&&) noexcept {}
71   enable_lw_shared_from_this(const enable_lw_shared_from_this&) noexcept {}
72   enable_lw_shared_from_this& operator=(const enable_lw_shared_from_this&) noexcept { return *this; }
73   enable_lw_shared_from_this& operator=(enable_lw_shared_from_this&&) noexcept { return *this; }
74  public:
75   lw_shared_ptr<T> shared_from_this();
76   lw_shared_ptr<const T> shared_from_this() const;
77   template <typename X>
78   friend class lw_shared_ptr;
79 };
80
81 template <typename T>
82 struct shared_ptr_no_esft {
83   T _value;
84   using ctor = shared_ptr_no_esft;
85
86   T* to_value() { return &_value; }
87   shared_ptr_no_esft* to_internal_object() { return this; }
88   shared_ptr_no_esft() = default;
89   shared_ptr_no_esft(const T& x) : _value(x) {}
90   shared_ptr_no_esft(T&& x) : _value(std::move(x)) {}
91   template <typename... A>
92   shared_ptr_no_esft(A&&... a) : _value(std::forward<A>(a)...) {}
93   template <typename X>
94   friend class lw_shared_ptr;
95 };
96
97 template <typename T>
98 using shared_ptr_impl = typename std::conditional<
99         std::is_base_of<enable_lw_shared_from_this<remove_const_t<T>>, T>::value,
100         enable_lw_shared_from_this<remove_const_t<T>>,
101         shared_ptr_no_esft<remove_const_t<T>> >::type;
102
103 template <typename T>
104 class lw_shared_ptr {
105   mutable shared_ptr_impl<T>* _p = nullptr;
106  private:
107   lw_shared_ptr(shared_ptr_impl<T>* p) noexcept : _p(p) {
108     if (_p) {
109       ++_p->_count;
110     }
111   }
112   template <typename... A>
113   static lw_shared_ptr make(A&&... a) {
114       return lw_shared_ptr(new typename shared_ptr_impl<T>::ctor(std::forward<A>(a)...));
115   }
116  public:
117   using element_type = T;
118
119   lw_shared_ptr() noexcept = default;
120   lw_shared_ptr(std::nullptr_t) noexcept : lw_shared_ptr() {}
121   lw_shared_ptr(const lw_shared_ptr& x) noexcept : _p(x._p) {
122     if (_p) {
123       ++_p->_count;
124     }
125   }
126   lw_shared_ptr(lw_shared_ptr&& x) noexcept  : _p(x._p) {
127       x._p = nullptr;
128   }
129   [[gnu::always_inline]]
130   ~lw_shared_ptr() {
131     if (_p && !--_p->_count) {
132       delete _p->to_internal_object();
133     }
134   }
135   lw_shared_ptr& operator=(const lw_shared_ptr& x) noexcept {
136       if (_p != x._p) {
137           this->~lw_shared_ptr();
138           new (this) lw_shared_ptr(x);
139       }
140       return *this;
141   }
142   lw_shared_ptr& operator=(lw_shared_ptr&& x) noexcept {
143       if (_p != x._p) {
144           this->~lw_shared_ptr();
145           new (this) lw_shared_ptr(std::move(x));
146       }
147       return *this;
148   }
149   lw_shared_ptr& operator=(std::nullptr_t) noexcept {
150       return *this = lw_shared_ptr();
151   }
152   lw_shared_ptr& operator=(T&& x) noexcept {
153       this->~lw_shared_ptr();
154       new (this) lw_shared_ptr(make_lw_shared<T>(std::move(x)));
155       return *this;
156   }
157
158   T& operator*() const noexcept { return *_p->to_value(); }
159   T* operator->() const noexcept { return _p->to_value(); }
160   T* get() const noexcept { return _p->to_value(); }
161
162   long int use_count() const noexcept {
163     if (_p) {
164       return _p->_count;
165     } else {
166       return 0;
167     }
168   }
169
170   operator lw_shared_ptr<const T>() const noexcept {
171       return lw_shared_ptr<const T>(_p);
172   }
173
174   explicit operator bool() const noexcept {
175       return _p;
176   }
177
178   bool owned() const noexcept {
179     return _p->_count == 1;
180   }
181
182   bool operator==(const lw_shared_ptr<const T>& x) const {
183       return _p == x._p;
184   }
185
186   bool operator!=(const lw_shared_ptr<const T>& x) const {
187       return !operator==(x);
188   }
189
190   bool operator==(const lw_shared_ptr<remove_const_t<T>>& x) const {
191       return _p == x._p;
192   }
193
194   bool operator!=(const lw_shared_ptr<remove_const_t<T>>& x) const {
195       return !operator==(x);
196   }
197
198   template <typename U>
199   friend class lw_shared_ptr;
200
201   template <typename X, typename... A>
202   friend lw_shared_ptr<X> make_lw_shared(A&&...);
203
204   template <typename U>
205   friend lw_shared_ptr<U> make_lw_shared(U&&);
206
207   template <typename U>
208   friend lw_shared_ptr<U> make_lw_shared(U&);
209
210   template <typename U>
211   friend class enable_lw_shared_from_this;
212 };
213
214 template <typename T, typename... A>
215 inline
216 lw_shared_ptr<T> make_lw_shared(A&&... a) {
217     return lw_shared_ptr<T>::make(std::forward<A>(a)...);
218 }
219
220 template <typename T>
221 inline
222 lw_shared_ptr<T> make_lw_shared(T&& a) {
223     return lw_shared_ptr<T>::make(std::move(a));
224 }
225
226 template <typename T>
227 inline
228 lw_shared_ptr<T> make_lw_shared(T& a) {
229     return lw_shared_ptr<T>::make(a);
230 }
231
232 template <typename T>
233 inline
234 lw_shared_ptr<T>
235 enable_lw_shared_from_this<T>::shared_from_this() {
236     return lw_shared_ptr<T>(this);
237 }
238
239 template <typename T>
240 inline
241 lw_shared_ptr<const T>
242 enable_lw_shared_from_this<T>::shared_from_this() const {
243     return lw_shared_ptr<const T>(const_cast<enable_lw_shared_from_this*>(this));
244 }
245
246 template <typename T>
247 static inline
248 std::ostream& operator<<(std::ostream& out, const lw_shared_ptr<T>& p) {
249     if (!p) {
250         return out << "null";
251     }
252     return out << *p;
253 }
254
255 namespace std {
256
257   template <typename T>
258   struct hash<lw_shared_ptr<T>> : private hash<T*> {
259     size_t operator()(const lw_shared_ptr<T>& p) const {
260         return hash<T*>::operator()(p.get());
261     }
262   };
263
264 }
265
266 #endif /* CEPH_LW_SHARED_PTR_H_ */