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 an owned smart pointer.
32  */
33 
34 #ifndef OWNED_PTR_HPP_
35 #define OWNED_PTR_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/ptr_wrapper.hpp"
40 
41 namespace ot {
42 
43 /**
44  * Represents an owned smart pointer.
45  *
46  * `OwnedPtr` acts as sole owner of the object it manages. An `OwnedPtr` is non-copyable (copy constructor is deleted)
47  * but the ownership can be transferred from one `OwnedPtr` to another using move semantics.
48  *
49  * The `Type` class MUST provide `Free()` method which frees the instance.
50  *
51  * @tparam Type  The pointer type.
52  *
53  */
54 template <class Type> class OwnedPtr : public Ptr<Type>
55 {
56     using Ptr<Type>::mPointer;
57 
58 public:
59     /**
60      * This is the default constructor for `OwnedPtr` initializing it as null.
61      *
62      */
63     OwnedPtr(void) = default;
64 
65     /**
66      * Initializes the `OwnedPtr` with a given pointer.
67      *
68      * The `OwnedPtr` takes the ownership of the object at @p aPointer.
69      *
70      * @param[in] aPointer  A pointer to object to initialize with.
71      *
72      */
OwnedPtr(Type * aPointer)73     explicit OwnedPtr(Type *aPointer)
74         : Ptr<Type>(aPointer)
75     {
76     }
77 
78     /**
79      * Initializes the `OwnedPtr` from another `OwnedPtr` using move semantics.
80      *
81      * The `OwnedPtr` takes over the ownership of the object from @p aOther. After this call, @p aOther will be null.
82      *
83      * @param[in] aOther   An rvalue reference to another `OwnedPtr`.
84      *
85      */
OwnedPtr(OwnedPtr && aOther)86     OwnedPtr(OwnedPtr &&aOther)
87     {
88         mPointer        = aOther.mPointer;
89         aOther.mPointer = nullptr;
90     }
91 
92     /**
93      * This is the destructor for `OwnedPtr`.
94      *
95      * Upon destruction, the `OwnedPtr` invokes `Free()` method on its managed object (if any).
96      *
97      */
~OwnedPtr(void)98     ~OwnedPtr(void) { Delete(); }
99 
100     /**
101      * Frees the owned object (if any).
102      *
103      * Invokes `Free()` method on the `Type` object owned by `OwnedPtr` (if any). It will also set the
104      * `OwnedPtr` to null.
105      *
106      */
Free(void)107     void Free(void)
108     {
109         Delete();
110         mPointer = nullptr;
111     }
112 
113     /**
114      * Frees the current object owned by `OwnedPtr` (if any) and replaces it with a new one.
115      *
116      * The method will `Free()` the current object managed by `OwnedPtr` (if different from @p aPointer) before taking
117      * the ownership of the object at @p aPointer. The method correctly handles a self `Reset()` (i.e., @p aPointer
118      * being the same pointer as the one currently managed by `OwnedPtr`).
119      *
120      * @param[in] aPointer   A pointer to the new object to replace with.
121      *
122      */
Reset(Type * aPointer=nullptr)123     void Reset(Type *aPointer = nullptr)
124     {
125         if (mPointer != aPointer)
126         {
127             Delete();
128             mPointer = aPointer;
129         }
130     }
131 
132     /**
133      * Releases the ownership of the current object in `OwnedPtr` (if any).
134      *
135      * After this call, the `OwnedPtr` will be null.
136      *
137      * @returns The pointer to the object owned by `OwnedPtr` or `nullptr` if `OwnedPtr` was null.
138      *
139      */
Release(void)140     Type *Release(void)
141     {
142         Type *pointer = mPointer;
143         mPointer      = nullptr;
144         return pointer;
145     }
146 
147     /**
148      * Allows passing of the ownership to another `OwnedPtr` using move semantics.
149      *
150      * @returns An rvalue reference of the pointer to move from.
151      *
152      */
PassOwnership(void)153     OwnedPtr &&PassOwnership(void) { return static_cast<OwnedPtr &&>(*this); }
154 
155     /**
156      * Overload the assignment operator `=` to replace the object owned by the `OwnedPtr` with another one
157      * using move semantics.
158      *
159      * The `OwnedPtr` first frees its current owned object (if there is any and it is different from @p aOther) before
160      * taking over the ownership of the object from @p aOther. This method correctly handles a self assignment (i.e.,
161      * assigning the pointer to itself).
162      *
163      * @param[in] aOther   An rvalue reference to an `OwnedPtr` to move from.
164      *
165      * @returns A reference to this `OwnedPtr`.
166      *
167      */
operator =(OwnedPtr && aOther)168     OwnedPtr &operator=(OwnedPtr &&aOther)
169     {
170         Reset(aOther.Release());
171         return *this;
172     }
173 
174     OwnedPtr(const OwnedPtr &)            = delete;
175     OwnedPtr(OwnedPtr &)                  = delete;
176     OwnedPtr &operator=(const OwnedPtr &) = delete;
177 
178 private:
Delete(void)179     void Delete(void)
180     {
181         if (mPointer != nullptr)
182         {
183             mPointer->Free();
184         }
185     }
186 };
187 
188 } // namespace ot
189 
190 #endif // OWNED_PTR_HPP_
191