Fix integer type used by ESet
[xapian.git] / xapian-core / include / xapian / intrusive_ptr.h
blobd55fa03ee4b5be96f9bbbf64d89840a68a6631b1
1 #ifndef XAPIAN_INCLUDED_INTRUSIVE_PTR_H
2 #define XAPIAN_INCLUDED_INTRUSIVE_PTR_H
4 //
5 // Based on Boost's intrusive_ptr.hpp
6 //
7 // Copyright (c) 2001, 2002 Peter Dimov
8 // Copyright (c) 2011,2013,2014,2015 Olly Betts
9 //
10 // Distributed under the Boost Software License, Version 1.0.
12 // Boost Software License - Version 1.0 - August 17th, 2003
14 // Permission is hereby granted, free of charge, to any person or organization
15 // obtaining a copy of the software and accompanying documentation covered by
16 // this license (the "Software") to use, reproduce, display, distribute,
17 // execute, and transmit the Software, and to prepare derivative works of the
18 // Software, and to permit third-parties to whom the Software is furnished to
19 // do so, all subject to the following:
21 // The copyright notices in the Software and this entire statement, including
22 // the above license grant, this restriction and the following disclaimer,
23 // must be included in all copies of the Software, in whole or in part, and
24 // all derivative works of the Software, unless such copies or derivative
25 // works are solely in the form of machine-executable object code generated by
26 // a source language processor.
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
31 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
32 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
33 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
34 // DEALINGS IN THE SOFTWARE.
36 // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
39 #if !defined XAPIAN_IN_XAPIAN_H && !defined XAPIAN_LIB_BUILD
40 # error Never use <xapian/intrusive_ptr.h> directly; include <xapian.h> instead.
41 #endif
43 #include <xapian/visibility.h>
45 namespace Xapian {
46 namespace Internal {
48 /// Base class for objects managed by intrusive_ptr.
49 class intrusive_base {
50 /// Prevent copying.
51 intrusive_base(const intrusive_base&);
53 /// Prevent assignment.
54 void operator=(const intrusive_base&);
56 public:
57 /** Construct with no references.
59 * The references get added if/when this object is put into an
60 * intrusive_ptr.
62 intrusive_base() : _refs(0) { }
64 /* There's no need for a virtual destructor here as we never delete a
65 * subclass of intrusive_base by calling delete on intrusive_base*.
68 /** Reference count.
70 * This needs to be mutable so we can add/remove references through const
71 * pointers.
73 mutable unsigned _refs;
77 // intrusive_ptr
80 /// A smart pointer that uses intrusive reference counting.
81 template<class T> class intrusive_ptr
83 private:
85 typedef intrusive_ptr this_type;
87 public:
89 intrusive_ptr(): px( 0 )
93 intrusive_ptr( T * p): px( p )
95 if( px != 0 ) ++px->_refs;
98 template<class U>
99 intrusive_ptr( intrusive_ptr<U> const & rhs )
100 : px( rhs.get() )
102 if( px != 0 ) ++px->_refs;
105 intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
107 if( px != 0 ) ++px->_refs;
110 ~intrusive_ptr()
112 if( px != 0 && --px->_refs == 0 ) delete px;
115 #ifdef XAPIAN_MOVE_SEMANTICS
116 intrusive_ptr(intrusive_ptr && rhs) : px( rhs.px )
118 rhs.px = 0;
121 intrusive_ptr & operator=(intrusive_ptr && rhs)
123 this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
124 return *this;
127 template<class U> friend class intrusive_ptr;
129 template<class U>
130 intrusive_ptr(intrusive_ptr<U> && rhs) : px( rhs.px )
132 rhs.px = 0;
135 template<class U>
136 intrusive_ptr & operator=(intrusive_ptr<U> && rhs)
138 this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
139 return *this;
141 #endif
143 intrusive_ptr & operator=(intrusive_ptr const & rhs)
145 this_type(rhs).swap(*this);
146 return *this;
149 intrusive_ptr & operator=(T * rhs)
151 this_type(rhs).swap(*this);
152 return *this;
155 T * get() const
157 return px;
160 T & operator*() const
162 return *px;
165 T * operator->() const
167 return px;
170 void swap(intrusive_ptr & rhs)
172 T * tmp = px;
173 px = rhs.px;
174 rhs.px = tmp;
177 private:
179 T * px;
182 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
184 return a.get() == b.get();
187 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
189 return a.get() != b.get();
192 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
194 return a.get() == b;
197 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
199 return a.get() != b;
202 template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
204 return a == b.get();
207 template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
209 return a != b.get();
212 /// Base class for objects managed by opt_intrusive_ptr.
213 class XAPIAN_VISIBILITY_DEFAULT opt_intrusive_base {
214 public:
215 opt_intrusive_base(const opt_intrusive_base&) : _refs(0) { }
217 opt_intrusive_base& operator=(const opt_intrusive_base&) {
218 // Don't touch _refs.
219 return *this;
222 /** Construct object which is initially not reference counted.
224 * The reference counting starts if release() is called.
226 opt_intrusive_base() : _refs(0) { }
228 /* Subclasses of opt_intrusive_base may be deleted by calling delete on a
229 * pointer to opt_intrusive_base.
231 virtual ~opt_intrusive_base() { }
233 void ref() const {
234 if (_refs == 0)
235 _refs = 2;
236 else
237 ++_refs;
240 void unref() const {
241 if (--_refs == 1)
242 delete this;
245 /** Reference count.
247 * This needs to be mutable so we can add/remove references through const
248 * pointers.
250 mutable unsigned _refs;
252 protected:
253 /** Start reference counting.
255 * The object is constructed with _refs set to 0, meaning it isn't being
256 * reference counted.
258 * Calling release() sets _refs to 1 if it is 0, and from then
259 * opt_intrusive_ptr will increment and decrement _refs. If it is
260 * decremented to 1, the object is deleted.
262 void release() const {
263 if (_refs == 0)
264 _refs = 1;
269 // opt_intrusive_ptr
272 /// A smart pointer that optionally uses intrusive reference counting.
273 template<class T> class opt_intrusive_ptr
275 private:
277 typedef opt_intrusive_ptr this_type;
279 public:
281 opt_intrusive_ptr(): px( 0 ), counting( false )
285 opt_intrusive_ptr( T * p): px( p ), counting( px != 0 && px->_refs )
287 if( counting ) ++px->_refs;
290 template<class U>
291 opt_intrusive_ptr( opt_intrusive_ptr<U> const & rhs )
292 : px( rhs.get() ), counting( rhs.counting )
294 if( counting ) ++px->_refs;
297 opt_intrusive_ptr(opt_intrusive_ptr const & rhs)
298 : px( rhs.px ), counting( rhs.counting )
300 if( counting ) ++px->_refs;
303 ~opt_intrusive_ptr()
305 if( counting && --px->_refs == 1 ) delete px;
308 #ifdef XAPIAN_MOVE_SEMANTICS
309 opt_intrusive_ptr(opt_intrusive_ptr && rhs)
310 : px( rhs.px ), counting( rhs.counting )
312 rhs.px = 0;
313 rhs.counting = 0;
316 opt_intrusive_ptr & operator=(opt_intrusive_ptr && rhs)
318 this_type( static_cast< opt_intrusive_ptr && >( rhs ) ).swap(*this);
319 return *this;
322 template<class U> friend class opt_intrusive_ptr;
324 template<class U>
325 opt_intrusive_ptr(opt_intrusive_ptr<U> && rhs)
326 : px( rhs.px ), counting( rhs.counting )
328 rhs.px = 0;
329 rhs.counting = 0;
332 template<class U>
333 opt_intrusive_ptr & operator=(opt_intrusive_ptr<U> && rhs)
335 this_type( static_cast< opt_intrusive_ptr<U> && >( rhs ) ).swap(*this);
336 return *this;
338 #endif
340 opt_intrusive_ptr & operator=(opt_intrusive_ptr const & rhs)
342 this_type(rhs).swap(*this);
343 return *this;
346 opt_intrusive_ptr & operator=(T * rhs)
348 this_type(rhs).swap(*this);
349 return *this;
352 T * get() const
354 return px;
357 T & operator*() const
359 return *px;
362 T * operator->() const
364 return px;
367 void swap(opt_intrusive_ptr & rhs)
369 T * tmp = px;
370 px = rhs.px;
371 rhs.px = tmp;
372 bool tmp2 = counting;
373 counting = rhs.counting;
374 rhs.counting = tmp2;
377 private:
379 T * px;
381 bool counting;
384 template<class T, class U> inline bool operator==(opt_intrusive_ptr<T> const & a, opt_intrusive_ptr<U> const & b)
386 return a.get() == b.get();
389 template<class T, class U> inline bool operator!=(opt_intrusive_ptr<T> const & a, opt_intrusive_ptr<U> const & b)
391 return a.get() != b.get();
394 template<class T, class U> inline bool operator==(opt_intrusive_ptr<T> const & a, U * b)
396 return a.get() == b;
399 template<class T, class U> inline bool operator!=(opt_intrusive_ptr<T> const & a, U * b)
401 return a.get() != b;
404 template<class T, class U> inline bool operator==(T * a, opt_intrusive_ptr<U> const & b)
406 return a == b.get();
409 template<class T, class U> inline bool operator!=(T * a, opt_intrusive_ptr<U> const & b)
411 return a != b.get();
417 #endif // XAPIAN_INCLUDED_INTRUSIVE_PTR_H