xref: /aosp_15_r20/external/pigweed/pw_intrusive_ptr/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_intrusive_ptr:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker----------------
4*61c4878aSAndroid Build Coastguard Workerpw_intrusive_ptr
5*61c4878aSAndroid Build Coastguard Worker----------------
6*61c4878aSAndroid Build Coastguard Worker
7*61c4878aSAndroid Build Coastguard WorkerIntrusivePtr
8*61c4878aSAndroid Build Coastguard Worker------------
9*61c4878aSAndroid Build Coastguard Worker``pw::IntrusivePtr`` is a smart shared pointer that relies on the pointed-at
10*61c4878aSAndroid Build Coastguard Workerobject to do the reference counting. Its API is based on ``std::shared_ptr`` but
11*61c4878aSAndroid Build Coastguard Workerrequires the pointed-at class to provide ``AddRef()`` and ``ReleaseRef()``
12*61c4878aSAndroid Build Coastguard Workermethods to do the reference counting. The easiest way to do that is to
13*61c4878aSAndroid Build Coastguard Workersubclass ``pw::RefCounted``. Doing this will provide atomic reference counting
14*61c4878aSAndroid Build Coastguard Workerand a ``Ptr`` type alias for the ``IntrusivePtr<T>``.
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Worker``IntrusivePtr`` doesn't provide any weak pointer ability.
17*61c4878aSAndroid Build Coastguard Worker
18*61c4878aSAndroid Build Coastguard Worker``IntrusivePtr`` with a ``RefCounted``-based class always guarantees atomic
19*61c4878aSAndroid Build Coastguard Workeroperations on the reference counter, whereas ``std::shared_ptr`` falls back to a
20*61c4878aSAndroid Build Coastguard Workernon-atomic control block when threading support is not enabled due to a design
21*61c4878aSAndroid Build Coastguard Workerfault in the STL implementation.
22*61c4878aSAndroid Build Coastguard Worker
23*61c4878aSAndroid Build Coastguard WorkerSimilar to ``std::shared_ptr``, ``IntrusivePtr`` doesn't provide any
24*61c4878aSAndroid Build Coastguard Workerthread-safety guarantees for the pointed-at object or for the pointer object
25*61c4878aSAndroid Build Coastguard Workeritself. I.e. assigning and reading the same ``IntrusivePtr`` from multiple
26*61c4878aSAndroid Build Coastguard Workerthreads without external lock is not allowed.
27*61c4878aSAndroid Build Coastguard Worker
28*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
29*61c4878aSAndroid Build Coastguard Worker
30*61c4878aSAndroid Build Coastguard Worker   class MyClass : public RefCounted<MyClass> {
31*61c4878aSAndroid Build Coastguard Worker   // ...
32*61c4878aSAndroid Build Coastguard Worker   };
33*61c4878aSAndroid Build Coastguard Worker
34*61c4878aSAndroid Build Coastguard Worker   // Empty pointer, equals to nullptr.
35*61c4878aSAndroid Build Coastguard Worker   // MyClass::Ptr is the same as IntrusivePtr<MyClass>.
36*61c4878aSAndroid Build Coastguard Worker   MyClass::Ptr empty_ptr = IntrusivePtr<MyClass>();
37*61c4878aSAndroid Build Coastguard Worker
38*61c4878aSAndroid Build Coastguard Worker   // Wrapping an externally created pointer.
39*61c4878aSAndroid Build Coastguard Worker   MyClass raw_ptr = new MyClass();
40*61c4878aSAndroid Build Coastguard Worker   MyClass::Ptr ptr_1 = MyClass::Ptr(raw_ptr);
41*61c4878aSAndroid Build Coastguard Worker   // raw_ptr shouldn't be used after this line if ptr_1 can go out of scope.
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker   // Using MakeRefCounted() helper.
44*61c4878aSAndroid Build Coastguard Worker   auto ptr_2 = MakeRefCounted<MyClass>(/* ... */);
45*61c4878aSAndroid Build Coastguard Worker
46*61c4878aSAndroid Build Coastguard Worker``IntrusivePtr`` can be passed as an argument by either const reference or
47*61c4878aSAndroid Build Coastguard Workervalue. Const reference is more preferable because it does not cause unnecessary
48*61c4878aSAndroid Build Coastguard Workercopies (which results in atomic operations on the ref count). Passing by value
49*61c4878aSAndroid Build Coastguard Workeris used when this ``IntrusivePtr`` is immediately stored (e.g. constructor that
50*61c4878aSAndroid Build Coastguard Workerstores ``IntrusivePtr`` in the object field). In this case passing by value and
51*61c4878aSAndroid Build Coastguard Workermove is more explicit in terms of intentions. It is also the behavior that
52*61c4878aSAndroid Build Coastguard Workerclang-tidy checks suggest.
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard Worker``IntrusivePtr`` should almost always be returned by value. The only case when
55*61c4878aSAndroid Build Coastguard Workerit can be returned by const reference is the trivial getter for the object
56*61c4878aSAndroid Build Coastguard Workerfield. When returning locally created ``IntrusivePtr`` or a pointer that was
57*61c4878aSAndroid Build Coastguard Workercasted to the base class it MUST be returned by value.
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard WorkerRecyclable
60*61c4878aSAndroid Build Coastguard Worker----------
61*61c4878aSAndroid Build Coastguard Worker``pw::Recyclable`` is a mixin that can be used with supported smart pointers
62*61c4878aSAndroid Build Coastguard Workerlike ``pw::IntrusivePtr`` to specify a custom memory cleanup routine instead
63*61c4878aSAndroid Build Coastguard Workerof `delete`. The cleanup routine is specified as a method with the signature
64*61c4878aSAndroid Build Coastguard Worker``void pw_recycle()``. For example:
65*61c4878aSAndroid Build Coastguard Worker
66*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker   class Foo : public pw::Recyclable<Foo>, public pw::IntrusivePtr<Foo> {
69*61c4878aSAndroid Build Coastguard Worker   public:
70*61c4878aSAndroid Build Coastguard Worker     // public implementation here
71*61c4878aSAndroid Build Coastguard Worker   private:
72*61c4878aSAndroid Build Coastguard Worker     friend class pw::Recyclable<Foo>;
73*61c4878aSAndroid Build Coastguard Worker     void pw_recycle() {
74*61c4878aSAndroid Build Coastguard Worker       if (should_recycle())) {
75*61c4878aSAndroid Build Coastguard Worker         do_recycle_stuff();
76*61c4878aSAndroid Build Coastguard Worker       } else {
77*61c4878aSAndroid Build Coastguard Worker         delete this;
78*61c4878aSAndroid Build Coastguard Worker       }
79*61c4878aSAndroid Build Coastguard Worker     }
80*61c4878aSAndroid Build Coastguard Worker   };
81*61c4878aSAndroid Build Coastguard Worker
82*61c4878aSAndroid Build Coastguard Worker``Recyclable`` can be used to avoid heap allocation when using smart pointers,
83*61c4878aSAndroid Build Coastguard Workeras the recycle routine can return memory to a memory pool.
84