blob: daf67943527d4432d3ce63c6e183e78b6ee9b389 [file] [log] [blame]
Brian Silverman355f11d2018-08-04 23:57:00 -07001////
2Copyright 2003-2005, 2013, 2017 Peter Dimov
3
4Distributed under the Boost Software License, Version 1.0.
5
6See accompanying file LICENSE_1_0.txt or copy at
7http://www.boost.org/LICENSE_1_0.txt
8////
9
10[#intrusive_ptr]
11# intrusive_ptr: Managing Objects with Embedded Counts
12:toc:
13:toc-title:
14:idprefix: intrusive_ptr_
15
16## Description
17
18The `intrusive_ptr` class template stores a pointer to an object with an embedded reference count.
19Every new `intrusive_ptr` instance increments the reference count by using an unqualified call to the
20function `intrusive_ptr_add_ref`, passing it the pointer as an argument. Similarly, when an `intrusive_ptr`
21is destroyed, it calls `intrusive_ptr_release`; this function is responsible for destroying the object when
22its reference count drops to zero. The user is expected to provide suitable definitions of these two functions.
23On compilers that support argument-dependent lookup, `intrusive_ptr_add_ref` and `intrusive_ptr_release` should
24be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace
25`boost`. The library provides a helper base class template `<<intrusive_ref_counter,intrusive_ref_counter>>` which
26may help adding support for `intrusive_ptr` to user types.
27
28The class template is parameterized on `T`, the type of the object pointed to. `intrusive_ptr<T>` can be implicitly
29converted to `intrusive_ptr<U>` whenever `T*` can be implicitly converted to `U*`.
30
31The main reasons to use `intrusive_ptr` are:
32
33* Some existing frameworks or OSes provide objects with embedded reference counts;
34* The memory footprint of `intrusive_ptr` is the same as the corresponding raw pointer;
35* `intrusive_ptr<T>` can be constructed from an arbitrary raw pointer of type `T*`.
36
37As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your needs than `shared_ptr`, try a `shared_ptr`-based design first.
38
39## Synopsis
40
41`intrusive_ptr` is defined in `<boost/smart_ptr/intrusive_ptr.hpp>`.
42
43```
44namespace boost {
45
46 template<class T> class intrusive_ptr {
47 public:
48
49 typedef T element_type;
50
51 intrusive_ptr() noexcept;
52 intrusive_ptr(T * p, bool add_ref = true);
53
54 intrusive_ptr(intrusive_ptr const & r);
55 template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
56
57 ~intrusive_ptr();
58
59 intrusive_ptr & operator=(intrusive_ptr const & r);
60 template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
61 intrusive_ptr & operator=(T * r);
62
63 void reset();
64 void reset(T * r);
65 void reset(T * r, bool add_ref);
66
67 T & operator*() const noexcept;
68 T * operator->() const noexcept;
69 T * get() const noexcept;
70 T * detach() noexcept;
71
72 explicit operator bool () const noexcept;
73
74 void swap(intrusive_ptr & b) noexept;
75 };
76
77 template<class T, class U>
78 bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
79
80 template<class T, class U>
81 bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
82
83 template<class T, class U>
84 bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
85
86 template<class T, class U>
87 bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
88
89 template<class T, class U>
90 bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
91
92 template<class T, class U>
93 bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
94
95 template<class T, class U>
96 bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
97
98 template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
99
100 template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
101
102 template<class T, class U>
103 intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
104
105 template<class T, class U>
106 intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
107
108 template<class T, class U>
109 intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
110
111 template<class E, class T, class Y>
112 std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
113 intrusive_ptr<Y> const & p);
114}
115```
116
117## Members
118
119### element_type
120
121```
122typedef T element_type;
123```
124
125Provides the type of the template parameter T.
126
127### constructors
128
129```
130intrusive_ptr() noexcept;
131```
132
133[none]
134* {blank}
135+
136Postconditions:: `get() == 0`.
137
138```
139intrusive_ptr(T * p, bool add_ref = true);
140```
141
142[none]
143* {blank}
144+
145Effects:: `if(p != 0 && add_ref) intrusive_ptr_add_ref(p);`.
146Postconditions:: `get() == p`.
147
148```
149intrusive_ptr(intrusive_ptr const & r);
150```
151```
152template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
153```
154
155[none]
156* {blank}
157+
158Effects:: `T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);`.
159Postconditions:: `get() == r.get()`.
160
161### destructor
162
163```
164~intrusive_ptr();
165```
166
167[none]
168* {blank}
169+
170Effects:: `if(get() != 0) intrusive_ptr_release(get());`.
171
172### assignment
173
174```
175intrusive_ptr & operator=(intrusive_ptr const & r);
176```
177```
178template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
179```
180```
181intrusive_ptr & operator=(T * r);
182```
183
184[none]
185* {blank}
186+
187Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`.
188Returns:: `*this`.
189
190### reset
191
192```
193void reset();
194```
195
196[none]
197* {blank}
198+
199Effects:: Equivalent to `intrusive_ptr().swap(*this)`.
200
201```
202void reset(T * r);
203```
204
205[none]
206* {blank}
207+
208Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`.
209
210```
211void reset(T * r, bool add_ref);
212```
213
214[none]
215* {blank}
216+
217Effects:: Equivalent to `intrusive_ptr(r, add_ref).swap(*this)`.
218
219### indirection
220
221```
222T & operator*() const noexcept;
223```
224
225[none]
226* {blank}
227+
228Requirements:: `get() != 0`.
229Returns:: `*get()`.
230
231```
232T * operator->() const noexcept;
233```
234
235[none]
236* {blank}
237+
238Requirements:: `get() != 0`.
239Returns:: `get()`.
240
241### get
242
243```
244T * get() const noexcept;
245```
246
247[none]
248* {blank}
249+
250Returns:: the stored pointer.
251
252### detach
253
254```
255T * detach() noexcept;
256```
257
258[none]
259* {blank}
260+
261Returns:: the stored pointer.
262Postconditions:: `get() == 0`.
263
264NOTE: The returned pointer has an elevated reference count. This allows conversion of an `intrusive_ptr`
265back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference.
266It can be viewed as the complement of the non-reference-incrementing constructor.
267
268CAUTION: Using `detach` escapes the safety of automatic reference counting provided by `intrusive_ptr`.
269It should by used only where strictly necessary (such as when interfacing to an existing API), and when
270the implications are thoroughly understood.
271
272### conversions
273
274```
275explicit operator bool () const noexcept;
276```
277
278[none]
279* {blank}
280+
281Returns:: `get() != 0`.
282
283NOTE: This conversion operator allows `intrusive_ptr` objects to be used in boolean contexts,
284like `if (p && p\->valid()) {}`.
285
286NOTE: On C++03 compilers, the return value is of an unspecified type.
287
288### swap
289
290```
291void swap(intrusive_ptr & b) noexcept;
292```
293
294[none]
295* {blank}
296+
297Effects:: Exchanges the contents of the two smart pointers.
298
299## Free Functions
300
301### comparison
302
303```
304template<class T, class U>
305 bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
306```
307
308[none]
309* {blank}
310+
311Returns:: `a.get() == b.get()`.
312
313```
314template<class T, class U>
315 bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
316```
317
318[none]
319* {blank}
320+
321Returns:: `a.get() != b.get()`.
322
323```
324template<class T, class U>
325 bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
326```
327
328[none]
329* {blank}
330+
331Returns:: `a.get() == b`.
332
333```
334template<class T, class U>
335 bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
336```
337
338[none]
339* {blank}
340+
341Returns:: `a.get() != b`.
342
343```
344template<class T, class U>
345 bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
346```
347
348[none]
349* {blank}
350+
351Returns:: `a == b.get()`.
352
353```
354template<class T, class U>
355 bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
356```
357
358[none]
359* {blank}
360+
361Returns:: `a != b.get()`.
362
363```
364template<class T, class U>
365 bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
366```
367
368[none]
369* {blank}
370+
371Returns:: `std::less<T *>()(a.get(), b.get())`.
372
373NOTE: Allows `intrusive_ptr` objects to be used as keys in associative containers.
374
375### swap
376
377```
378template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
379```
380
381[none]
382* {blank}
383+
384Effects:: Equivalent to `a.swap(b)`.
385
386### get_pointer
387
388```
389template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
390```
391
392[none]
393* {blank}
394+
395Returns:: `p.get()`.
396
397NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
398
399### static_pointer_cast
400
401```
402template<class T, class U>
403 intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
404```
405
406[none]
407* {blank}
408+
409Returns:: `intrusive_ptr<T>(static_cast<T*>(r.get()))`.
410
411### const_pointer_cast
412
413```
414template<class T, class U>
415 intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
416```
417
418[none]
419* {blank}
420+
421Returns:: `intrusive_ptr<T>(const_cast<T*>(r.get()))`.
422
423### dynamic_pointer_cast
424
425```
426template<class T, class U>
427 intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
428```
429
430[none]
431* {blank}
432+
433Returns:: `intrusive_ptr<T>(dynamic_cast<T*>(r.get()))`.
434
435### operator<<
436
437```
438template<class E, class T, class Y>
439 std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
440 intrusive_ptr<Y> const & p);
441```
442
443[none]
444* {blank}
445+
446Effects:: `os << p.get();`.
447Returns:: `os`.