xapian-core  1.4.25
intrusive_ptr.h
Go to the documentation of this file.
1 #ifndef XAPIAN_INCLUDED_INTRUSIVE_PTR_H
2 #define XAPIAN_INCLUDED_INTRUSIVE_PTR_H
3 
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.
11 //
12 // Boost Software License - Version 1.0 - August 17th, 2003
13 //
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:
20 //
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.
27 //
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.
35 //
36 // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
37 //
38 
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
42 
43 #include <xapian/visibility.h>
44 
45 namespace Xapian {
46 namespace Internal {
47 
52 
54  void operator=(const intrusive_base&);
55 
56  public:
62  intrusive_base() : _refs(0) { }
63 
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*.
66  */
67 
73  mutable unsigned _refs;
74 };
75 
76 //
77 // intrusive_ptr
78 //
79 
81 template<class T> class intrusive_ptr
82 {
83 private:
84 
86 
87 public:
88 
89  intrusive_ptr(): px( 0 )
90  {
91  }
92 
93  intrusive_ptr( T * p): px( p )
94  {
95  if( px != 0 ) ++px->_refs;
96  }
97 
98  template<class U>
100  : px( rhs.get() )
101  {
102  if( px != 0 ) ++px->_refs;
103  }
104 
105  intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
106  {
107  if( px != 0 ) ++px->_refs;
108  }
109 
111  {
112  if( px != 0 && --px->_refs == 0 ) delete px;
113  }
114 
115 #ifdef XAPIAN_MOVE_SEMANTICS
116  intrusive_ptr(intrusive_ptr && rhs) : px( rhs.px )
117  {
118  rhs.px = 0;
119  }
120 
122  {
123  this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
124  return *this;
125  }
126 
127  template<class U> friend class intrusive_ptr;
128 
129  template<class U>
130  intrusive_ptr(intrusive_ptr<U> && rhs) : px( rhs.px )
131  {
132  rhs.px = 0;
133  }
134 
135  template<class U>
137  {
138  this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
139  return *this;
140  }
141 #endif
142 
144  {
145  this_type(rhs).swap(*this);
146  return *this;
147  }
148 
150  {
151  this_type(rhs).swap(*this);
152  return *this;
153  }
154 
155  T * get() const
156  {
157  return px;
158  }
159 
160  T & operator*() const
161  {
162  return *px;
163  }
164 
165  T * operator->() const
166  {
167  return px;
168  }
169 
170  void swap(intrusive_ptr & rhs)
171  {
172  T * tmp = px;
173  px = rhs.px;
174  rhs.px = tmp;
175  }
176 
177 private:
178 
179  T * px;
180 };
181 
182 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
183 {
184  return a.get() == b.get();
185 }
186 
187 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
188 {
189  return a.get() != b.get();
190 }
191 
192 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
193 {
194  return a.get() == b;
195 }
196 
197 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
198 {
199  return a.get() != b;
200 }
201 
202 template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
203 {
204  return a == b.get();
205 }
206 
207 template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
208 {
209  return a != b.get();
210 }
211 
214  public:
216 
218  // Don't touch _refs.
219  return *this;
220  }
221 
227 
228  /* Subclasses of opt_intrusive_base may be deleted by calling delete on a
229  * pointer to opt_intrusive_base.
230  */
231  virtual ~opt_intrusive_base() { }
232 
233  void ref() const {
234  if (_refs == 0)
235  _refs = 2;
236  else
237  ++_refs;
238  }
239 
240  void unref() const {
241  if (--_refs == 1)
242  delete this;
243  }
244 
250  mutable unsigned _refs;
251 
252  protected:
262  void release() const {
263  if (_refs == 0)
264  _refs = 1;
265  }
266 };
267 
268 //
269 // opt_intrusive_ptr
270 //
271 
273 template<class T> class opt_intrusive_ptr
274 {
275 private:
276 
278 
279 public:
280 
281  opt_intrusive_ptr(): px( 0 ), counting( false )
282  {
283  }
284 
285  opt_intrusive_ptr( T * p): px( p ), counting( px != 0 && px->_refs )
286  {
287  if( counting ) ++px->_refs;
288  }
289 
290  template<class U>
292  : px( rhs.get() ), counting( rhs.counting )
293  {
294  if( counting ) ++px->_refs;
295  }
296 
298  : px( rhs.px ), counting( rhs.counting )
299  {
300  if( counting ) ++px->_refs;
301  }
302 
304  {
305  if( counting && --px->_refs == 1 ) delete px;
306  }
307 
308 #ifdef XAPIAN_MOVE_SEMANTICS
310  : px( rhs.px ), counting( rhs.counting )
311  {
312  rhs.px = 0;
313  rhs.counting = 0;
314  }
315 
317  {
318  this_type( static_cast< opt_intrusive_ptr && >( rhs ) ).swap(*this);
319  return *this;
320  }
321 
322  template<class U> friend class opt_intrusive_ptr;
323 
324  template<class U>
326  : px( rhs.px ), counting( rhs.counting )
327  {
328  rhs.px = 0;
329  rhs.counting = 0;
330  }
331 
332  template<class U>
334  {
335  this_type( static_cast< opt_intrusive_ptr<U> && >( rhs ) ).swap(*this);
336  return *this;
337  }
338 #endif
339 
341  {
342  this_type(rhs).swap(*this);
343  return *this;
344  }
345 
347  {
348  this_type(rhs).swap(*this);
349  return *this;
350  }
351 
352  T * get() const
353  {
354  return px;
355  }
356 
357  T & operator*() const
358  {
359  return *px;
360  }
361 
362  T * operator->() const
363  {
364  return px;
365  }
366 
368  {
369  T * tmp = px;
370  px = rhs.px;
371  rhs.px = tmp;
372  bool tmp2 = counting;
373  counting = rhs.counting;
374  rhs.counting = tmp2;
375  }
376 
377 private:
378 
379  T * px;
380 
381  bool counting;
382 };
383 
384 template<class T, class U> inline bool operator==(opt_intrusive_ptr<T> const & a, opt_intrusive_ptr<U> const & b)
385 {
386  return a.get() == b.get();
387 }
388 
389 template<class T, class U> inline bool operator!=(opt_intrusive_ptr<T> const & a, opt_intrusive_ptr<U> const & b)
390 {
391  return a.get() != b.get();
392 }
393 
394 template<class T, class U> inline bool operator==(opt_intrusive_ptr<T> const & a, U * b)
395 {
396  return a.get() == b;
397 }
398 
399 template<class T, class U> inline bool operator!=(opt_intrusive_ptr<T> const & a, U * b)
400 {
401  return a.get() != b;
402 }
403 
404 template<class T, class U> inline bool operator==(T * a, opt_intrusive_ptr<U> const & b)
405 {
406  return a == b.get();
407 }
408 
409 template<class T, class U> inline bool operator!=(T * a, opt_intrusive_ptr<U> const & b)
410 {
411  return a != b.get();
412 }
413 
414 }
415 }
416 
417 #endif // XAPIAN_INCLUDED_INTRUSIVE_PTR_H
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:80
bool operator==(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b)
intrusive_ptr & operator=(T *rhs)
intrusive_base()
Construct with no references.
Definition: intrusive_ptr.h:62
opt_intrusive_ptr(opt_intrusive_ptr< U > const &rhs)
unsigned _refs
Reference count.
Definition: intrusive_ptr.h:73
intrusive_ptr(intrusive_ptr< U > const &rhs)
Definition: intrusive_ptr.h:99
void operator=(const intrusive_base &)
Prevent assignment.
opt_intrusive_ptr & operator=(opt_intrusive_ptr const &rhs)
#define false
Definition: header.h:9
opt_intrusive_base & operator=(const opt_intrusive_base &)
#define XAPIAN_VISIBILITY_DEFAULT
Definition: visibility.h:28
opt_intrusive_ptr & operator=(T *rhs)
Define XAPIAN_VISIBILITY_* macros.
opt_intrusive_base(const opt_intrusive_base &)
void swap(opt_intrusive_ptr &rhs)
opt_intrusive_ptr(opt_intrusive_ptr const &rhs)
Base class for objects managed by intrusive_ptr.
Definition: intrusive_ptr.h:49
Base class for objects managed by opt_intrusive_ptr.
unsigned _refs
Reference count.
opt_intrusive_base()
Construct object which is initially not reference counted.
void swap(intrusive_ptr &rhs)
intrusive_ptr & operator=(intrusive_ptr const &rhs)
A smart pointer that optionally uses intrusive reference counting.
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:81
intrusive_ptr(intrusive_ptr const &rhs)
bool operator!=(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b)
void release() const
Start reference counting.