]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp | |
4 | // | |
5 | // (C) Copyright Peter Dimov 2001, 2002 | |
6 | // (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost | |
7 | // Software License, Version 1.0. (See accompanying file | |
8 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | // See http://www.boost.org/libs/interprocess for documentation. | |
11 | // | |
12 | ////////////////////////////////////////////////////////////////////////////// | |
13 | ||
14 | #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED | |
15 | #define BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED | |
16 | ||
17 | #ifndef BOOST_CONFIG_HPP | |
18 | # include <boost/config.hpp> | |
19 | #endif | |
20 | # | |
21 | #if defined(BOOST_HAS_PRAGMA_ONCE) | |
22 | # pragma once | |
23 | #endif | |
24 | ||
25 | //!\file | |
26 | //!Describes an intrusive ownership pointer. | |
27 | ||
28 | #include <boost/interprocess/detail/config_begin.hpp> | |
29 | #include <boost/interprocess/detail/workaround.hpp> | |
30 | ||
31 | #include <boost/assert.hpp> | |
32 | #include <boost/interprocess/detail/utilities.hpp> | |
33 | #include <boost/intrusive/pointer_traits.hpp> | |
34 | #include <boost/move/adl_move_swap.hpp> | |
11fdf7f2 | 35 | #include <boost/move/core.hpp> |
7c673cae FG |
36 | |
37 | #include <iosfwd> // for std::basic_ostream | |
38 | ||
39 | #include <boost/intrusive/detail/minimal_less_equal_header.hpp> //std::less | |
40 | ||
41 | namespace boost { | |
42 | namespace interprocess { | |
43 | ||
44 | //!The intrusive_ptr class template stores a pointer to an object | |
45 | //!with an embedded reference count. intrusive_ptr is parameterized on | |
46 | //!T (the type of the object pointed to) and VoidPointer(a void pointer type | |
47 | //!that defines the type of pointer that intrusive_ptr will store). | |
48 | //!intrusive_ptr<T, void *> defines a class with a T* member whereas | |
49 | //!intrusive_ptr<T, offset_ptr<void> > defines a class with a offset_ptr<T> member. | |
50 | //!Relies on unqualified calls to: | |
51 | //! | |
11fdf7f2 TL |
52 | //! void intrusive_ptr_add_ref(T * p) BOOST_NOEXCEPT; |
53 | //! void intrusive_ptr_release(T * p) BOOST_NOEXCEPT; | |
7c673cae FG |
54 | //! |
55 | //! with (p != 0) | |
56 | //! | |
57 | //!The object is responsible for destroying itself. | |
58 | template<class T, class VoidPointer> | |
59 | class intrusive_ptr | |
60 | { | |
61 | public: | |
62 | //!Provides the type of the internal stored pointer. | |
63 | typedef typename boost::intrusive:: | |
64 | pointer_traits<VoidPointer>::template | |
65 | rebind_pointer<T>::type pointer; | |
66 | //!Provides the type of the stored pointer. | |
67 | typedef T element_type; | |
68 | ||
69 | #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) | |
70 | private: | |
71 | typedef VoidPointer VP; | |
72 | typedef intrusive_ptr this_type; | |
73 | typedef pointer this_type::*unspecified_bool_type; | |
74 | #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED | |
75 | ||
11fdf7f2 TL |
76 | BOOST_COPYABLE_AND_MOVABLE(intrusive_ptr) |
77 | ||
7c673cae FG |
78 | public: |
79 | //!Constructor. Initializes internal pointer to 0. | |
80 | //!Does not throw | |
11fdf7f2 TL |
81 | intrusive_ptr() BOOST_NOEXCEPT |
82 | : m_ptr(0) | |
7c673cae FG |
83 | {} |
84 | ||
85 | //!Constructor. Copies pointer and if "p" is not zero and | |
86 | //!"add_ref" is true calls intrusive_ptr_add_ref(to_raw_pointer(p)). | |
87 | //!Does not throw | |
11fdf7f2 TL |
88 | intrusive_ptr(const pointer &p, bool add_ref = true) BOOST_NOEXCEPT |
89 | : m_ptr(p) | |
7c673cae FG |
90 | { |
91 | if(m_ptr != 0 && add_ref) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); | |
92 | } | |
93 | ||
94 | //!Copy constructor. Copies the internal pointer and if "p" is not | |
95 | //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw | |
11fdf7f2 | 96 | intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT |
7c673cae FG |
97 | : m_ptr(rhs.m_ptr) |
98 | { | |
99 | if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); | |
100 | } | |
101 | ||
11fdf7f2 TL |
102 | //!Move constructor. Moves the internal pointer. Does not throw |
103 | intrusive_ptr(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT | |
104 | : m_ptr(rhs.m_ptr) | |
105 | { | |
106 | rhs.m_ptr = 0; | |
107 | } | |
108 | ||
7c673cae FG |
109 | //!Constructor from related. Copies the internal pointer and if "p" is not |
110 | //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw | |
11fdf7f2 | 111 | template<class U> intrusive_ptr(intrusive_ptr<U, VP> const & rhs) BOOST_NOEXCEPT |
7c673cae FG |
112 | : m_ptr(rhs.get()) |
113 | { | |
114 | if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr)); | |
115 | } | |
116 | ||
11fdf7f2 | 117 | //!Destructor. Calls reset(). Does not throw |
7c673cae FG |
118 | ~intrusive_ptr() |
119 | { | |
11fdf7f2 | 120 | reset(); |
7c673cae FG |
121 | } |
122 | ||
123 | //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). | |
124 | //!Does not throw | |
11fdf7f2 | 125 | intrusive_ptr & operator=(BOOST_COPY_ASSIGN_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT |
7c673cae FG |
126 | { |
127 | this_type(rhs).swap(*this); | |
128 | return *this; | |
129 | } | |
130 | ||
11fdf7f2 TL |
131 | //!Move Assignment operator |
132 | //!Does not throw | |
133 | intrusive_ptr & operator=(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT | |
134 | { | |
135 | rhs.swap(*this); | |
136 | rhs.reset(); | |
137 | return *this; | |
138 | } | |
139 | ||
7c673cae FG |
140 | //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). |
141 | //!Does not throw | |
11fdf7f2 | 142 | template<class U> intrusive_ptr & operator=(intrusive_ptr<U, VP> const & rhs) BOOST_NOEXCEPT |
7c673cae FG |
143 | { |
144 | this_type(rhs).swap(*this); | |
145 | return *this; | |
146 | } | |
147 | ||
148 | //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). | |
149 | //!Does not throw | |
11fdf7f2 | 150 | intrusive_ptr & operator=(pointer rhs) BOOST_NOEXCEPT |
7c673cae FG |
151 | { |
152 | this_type(rhs).swap(*this); | |
153 | return *this; | |
154 | } | |
155 | ||
11fdf7f2 TL |
156 | //!Release internal pointer and set it to 0. If internal pointer is not 0, calls |
157 | //!intrusive_ptr_release(to_raw_pointer(m_ptr)). Does not throw | |
158 | void reset() BOOST_NOEXCEPT { | |
159 | if(m_ptr != 0) { | |
160 | pointer ptr = m_ptr; | |
161 | m_ptr = 0; | |
162 | intrusive_ptr_release(ipcdetail::to_raw_pointer(ptr)); | |
163 | } | |
164 | } | |
165 | ||
7c673cae FG |
166 | //!Returns a reference to the internal pointer. |
167 | //!Does not throw | |
11fdf7f2 | 168 | pointer &get() BOOST_NOEXCEPT |
7c673cae FG |
169 | { return m_ptr; } |
170 | ||
171 | //!Returns a reference to the internal pointer. | |
172 | //!Does not throw | |
11fdf7f2 | 173 | const pointer &get() const BOOST_NOEXCEPT |
7c673cae FG |
174 | { return m_ptr; } |
175 | ||
176 | //!Returns *get(). | |
177 | //!Does not throw | |
11fdf7f2 | 178 | T & operator*() const BOOST_NOEXCEPT |
7c673cae FG |
179 | { return *m_ptr; } |
180 | ||
181 | //!Returns *get(). | |
182 | //!Does not throw | |
11fdf7f2 | 183 | const pointer &operator->() const BOOST_NOEXCEPT |
7c673cae FG |
184 | { return m_ptr; } |
185 | ||
186 | //!Returns get(). | |
187 | //!Does not throw | |
11fdf7f2 | 188 | pointer &operator->() BOOST_NOEXCEPT |
7c673cae FG |
189 | { return m_ptr; } |
190 | ||
191 | //!Conversion to boolean. | |
192 | //!Does not throw | |
11fdf7f2 | 193 | operator unspecified_bool_type () const BOOST_NOEXCEPT |
7c673cae FG |
194 | { return m_ptr == 0? 0: &this_type::m_ptr; } |
195 | ||
196 | //!Not operator. | |
197 | //!Does not throw | |
11fdf7f2 | 198 | bool operator! () const BOOST_NOEXCEPT |
7c673cae FG |
199 | { return m_ptr == 0; } |
200 | ||
201 | //!Exchanges the contents of the two smart pointers. | |
202 | //!Does not throw | |
11fdf7f2 | 203 | void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT |
7c673cae FG |
204 | { ::boost::adl_move_swap(m_ptr, rhs.m_ptr); } |
205 | ||
206 | #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) | |
207 | private: | |
208 | pointer m_ptr; | |
209 | #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED | |
210 | }; | |
211 | ||
212 | //!Returns a.get() == b.get(). | |
213 | //!Does not throw | |
214 | template<class T, class U, class VP> inline | |
215 | bool operator==(intrusive_ptr<T, VP> const & a, | |
11fdf7f2 | 216 | intrusive_ptr<U, VP> const & b) BOOST_NOEXCEPT |
7c673cae FG |
217 | { return a.get() == b.get(); } |
218 | ||
219 | //!Returns a.get() != b.get(). | |
220 | //!Does not throw | |
221 | template<class T, class U, class VP> inline | |
222 | bool operator!=(intrusive_ptr<T, VP> const & a, | |
11fdf7f2 | 223 | intrusive_ptr<U, VP> const & b) BOOST_NOEXCEPT |
7c673cae FG |
224 | { return a.get() != b.get(); } |
225 | ||
226 | //!Returns a.get() == b. | |
227 | //!Does not throw | |
228 | template<class T, class VP> inline | |
229 | bool operator==(intrusive_ptr<T, VP> const & a, | |
11fdf7f2 | 230 | const typename intrusive_ptr<T, VP>::pointer &b) BOOST_NOEXCEPT |
7c673cae FG |
231 | { return a.get() == b; } |
232 | ||
233 | //!Returns a.get() != b. | |
234 | //!Does not throw | |
235 | template<class T, class VP> inline | |
236 | bool operator!=(intrusive_ptr<T, VP> const & a, | |
11fdf7f2 | 237 | const typename intrusive_ptr<T, VP>::pointer &b) BOOST_NOEXCEPT |
7c673cae FG |
238 | { return a.get() != b; } |
239 | ||
240 | //!Returns a == b.get(). | |
241 | //!Does not throw | |
242 | template<class T, class VP> inline | |
243 | bool operator==(const typename intrusive_ptr<T, VP>::pointer &a, | |
11fdf7f2 | 244 | intrusive_ptr<T, VP> const & b) BOOST_NOEXCEPT |
7c673cae FG |
245 | { return a == b.get(); } |
246 | ||
247 | //!Returns a != b.get(). | |
248 | //!Does not throw | |
249 | template<class T, class VP> inline | |
250 | bool operator!=(const typename intrusive_ptr<T, VP>::pointer &a, | |
11fdf7f2 | 251 | intrusive_ptr<T, VP> const & b) BOOST_NOEXCEPT |
7c673cae FG |
252 | { return a != b.get(); } |
253 | ||
254 | //!Returns a.get() < b.get(). | |
255 | //!Does not throw | |
256 | template<class T, class VP> inline | |
257 | bool operator<(intrusive_ptr<T, VP> const & a, | |
11fdf7f2 | 258 | intrusive_ptr<T, VP> const & b) BOOST_NOEXCEPT |
7c673cae FG |
259 | { |
260 | return std::less<typename intrusive_ptr<T, VP>::pointer>() | |
261 | (a.get(), b.get()); | |
262 | } | |
263 | ||
264 | //!Exchanges the contents of the two intrusive_ptrs. | |
265 | //!Does not throw | |
266 | template<class T, class VP> inline | |
267 | void swap(intrusive_ptr<T, VP> & lhs, | |
11fdf7f2 | 268 | intrusive_ptr<T, VP> & rhs) BOOST_NOEXCEPT |
7c673cae FG |
269 | { lhs.swap(rhs); } |
270 | ||
271 | // operator<< | |
272 | template<class E, class T, class Y, class VP> | |
273 | inline std::basic_ostream<E, T> & operator<< | |
11fdf7f2 | 274 | (std::basic_ostream<E, T> & os, intrusive_ptr<Y, VP> const & p) BOOST_NOEXCEPT |
7c673cae FG |
275 | { os << p.get(); return os; } |
276 | ||
277 | //!Returns p.get(). | |
278 | //!Does not throw | |
279 | template<class T, class VP> | |
280 | inline typename boost::interprocess::intrusive_ptr<T, VP>::pointer | |
11fdf7f2 | 281 | to_raw_pointer(intrusive_ptr<T, VP> p) BOOST_NOEXCEPT |
7c673cae FG |
282 | { return p.get(); } |
283 | ||
284 | /*Emulates static cast operator. Does not throw*/ | |
285 | /* | |
286 | template<class T, class U, class VP> | |
287 | inline boost::interprocess::intrusive_ptr<T, VP> static_pointer_cast | |
11fdf7f2 | 288 | (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT |
7c673cae FG |
289 | { return do_static_cast<U>(p.get()); } |
290 | */ | |
291 | /*Emulates const cast operator. Does not throw*/ | |
292 | /* | |
293 | template<class T, class U, class VP> | |
294 | inline boost::interprocess::intrusive_ptr<T, VP> const_pointer_cast | |
11fdf7f2 | 295 | (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT |
7c673cae FG |
296 | { return do_const_cast<U>(p.get()); } |
297 | */ | |
298 | ||
299 | /*Emulates dynamic cast operator. Does not throw*/ | |
300 | /* | |
301 | template<class T, class U, class VP> | |
302 | inline boost::interprocess::intrusive_ptr<T, VP> dynamic_pointer_cast | |
11fdf7f2 | 303 | (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT |
7c673cae FG |
304 | { return do_dynamic_cast<U>(p.get()); } |
305 | */ | |
306 | ||
307 | /*Emulates reinterpret cast operator. Does not throw*/ | |
308 | /* | |
309 | template<class T, class U, class VP> | |
310 | inline boost::interprocess::intrusive_ptr<T, VP>reinterpret_pointer_cast | |
11fdf7f2 | 311 | (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT |
7c673cae FG |
312 | { return do_reinterpret_cast<U>(p.get()); } |
313 | */ | |
314 | ||
315 | } // namespace interprocess | |
316 | ||
317 | #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) | |
318 | ||
319 | #if defined(_MSC_VER) && (_MSC_VER < 1400) | |
320 | //!Returns p.get(). | |
321 | //!Does not throw | |
322 | template<class T, class VP> | |
11fdf7f2 | 323 | inline T *to_raw_pointer(boost::interprocess::intrusive_ptr<T, VP> p) BOOST_NOEXCEPT |
7c673cae FG |
324 | { return p.get(); } |
325 | #endif | |
326 | ||
327 | #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED | |
328 | ||
329 | } // namespace boost | |
330 | ||
331 | #include <boost/interprocess/detail/config_end.hpp> | |
332 | ||
333 | #endif // #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED |