• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for a retain (reference counted) smart pointer.
32  */
33 
34 #ifndef RETAIN_PTR_HPP_
35 #define RETAIN_PTR_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/ptr_wrapper.hpp"
40 
41 namespace ot {
42 
43 /**
44  * Represents a retain (reference counted) smart pointer.
45  *
46  * The `Type` class MUST provide mechanism to track its current retain count. It MUST provide the following three
47  * methods:
48  *
49  *   - void      IncrementRetainCount(void);  (Increment the retain count).
50  *   - uint16_t  DecrementRetainCount(void);  (Decrement the retain count and return the value after decrement).
51  *   - void      Free(void);                  (Free the `Type` instance).
52  *
53  * The `Type` can inherit from `RetainCountable` which provides the retain counting methods.
54  *
55  * @tparam Type  The pointer type.
56  */
57 template <class Type> class RetainPtr : public Ptr<Type>
58 {
59     using Ptr<Type>::mPointer;
60 
61 public:
62     /**
63      * This is the default constructor for `RetainPtr` initializing it as null.
64      */
65     RetainPtr(void) = default;
66 
67     /**
68      * Initializes the `RetainPtr` with a given pointer.
69      *
70      * Upon construction the `RetainPtr` will increment the retain count on @p aPointer (if not null).
71      *
72      * @param[in] aPointer  A pointer to object to initialize with.
73      */
RetainPtr(Type * aPointer)74     explicit RetainPtr(Type *aPointer)
75         : Ptr<Type>(aPointer)
76     {
77         IncrementRetainCount();
78     }
79 
80     /**
81      * Initializes the `RetainPtr` from another `RetainPtr`.
82      *
83      * @param[in] aOther   Another `RetainPtr`.
84      */
RetainPtr(const RetainPtr & aOther)85     RetainPtr(const RetainPtr &aOther)
86         : Ptr<Type>(aOther.mPointer)
87     {
88         IncrementRetainCount();
89     }
90 
91     /**
92      * This is the destructor for `RetainPtr`.
93      *
94      * Upon destruction, the `RetainPtr` will decrement the retain count on the managed object (if not null) and
95      * free the object if its retain count reaches zero.
96      */
~RetainPtr(void)97     ~RetainPtr(void) { DecrementRetainCount(); }
98 
99     /**
100      * Replaces the managed object by `RetainPtr` with a new one.
101      *
102      * The method correctly handles a self `Reset()` (i.e., @p aPointer being the same pointer as the one currently
103      * managed by `RetainPtr`).
104      *
105      * @param[in] aPointer   A pointer to a new object to replace with.
106      */
Reset(Type * aPointer=nullptr)107     void Reset(Type *aPointer = nullptr)
108     {
109         if (aPointer != mPointer)
110         {
111             DecrementRetainCount();
112             mPointer = aPointer;
113             IncrementRetainCount();
114         }
115     }
116 
117     /**
118      * Releases the ownership of the current pointer in `RetainPtr` (if any) without changing its retain
119      * count.
120      *
121      * After this call, the `RetainPtr` will be null.
122      *
123      * @returns The pointer to the object managed by `RetainPtr` or `nullptr` if `RetainPtr` was null.
124      */
Release(void)125     Type *Release(void)
126     {
127         Type *pointer = mPointer;
128         mPointer      = nullptr;
129         return pointer;
130     }
131 
132     /**
133      * Overloads the assignment operator `=`.
134      *
135      * The `RetainPtr` first frees its current managed object (if there is any and it is different from @p aOther)
136      * before taking over the ownership of the object from @p aOther. This method correctly handles a self assignment
137      * (i.e., assigning the pointer to itself).
138      *
139      * @param[in] aOther   A reference to another `RetainPtr`.
140      *
141      * @returns A reference to this `RetainPtr`.
142      */
operator =(const RetainPtr & aOther)143     RetainPtr &operator=(const RetainPtr &aOther)
144     {
145         Reset(aOther.mPointer);
146         return *this;
147     }
148 
149 private:
IncrementRetainCount(void)150     void IncrementRetainCount(void)
151     {
152         if (mPointer != nullptr)
153         {
154             mPointer->IncrementRetainCount();
155         }
156     }
157 
DecrementRetainCount(void)158     void DecrementRetainCount(void)
159     {
160         if ((mPointer != nullptr) && (mPointer->DecrementRetainCount() == 0))
161         {
162             mPointer->Free();
163         }
164     }
165 };
166 
167 /**
168  * Provides mechanism to track retain count.
169  */
170 class RetainCountable
171 {
172     template <class Type> friend class RetainPtr;
173 
174 protected:
175     /**
176      * This constrictor initializes the object starting with retain count of zero.
177      */
RetainCountable(void)178     RetainCountable(void)
179         : mRetainCount(0)
180     {
181     }
182 
183     /**
184      * Returns the current retain count.
185      *
186      * @returns The current retain count.
187      */
GetRetainCount(void) const188     uint16_t GetRetainCount(void) const { return mRetainCount; }
189 
190     /**
191      * Increments the retain count.
192      */
IncrementRetainCount(void)193     void IncrementRetainCount(void) { ++mRetainCount; }
194 
195     /**
196      * Decrements the retain count.
197      *
198      * @returns The retain count value after decrementing it.
199      */
DecrementRetainCount(void)200     uint16_t DecrementRetainCount(void) { return --mRetainCount; }
201 
202 private:
203     uint16_t mRetainCount;
204 };
205 
206 } // namespace ot
207 
208 #endif // RETAIN_PTR_HPP_
209