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