diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 1090324a2..409e435af 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -415,6 +415,7 @@ openthread_core_files = [ "common/owned_ptr.hpp", "common/owning_list.hpp", "common/pool.hpp", + "common/ptr_wrapper.hpp", "common/random.hpp", "common/random_manager.cpp", "common/random_manager.hpp", diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 33f2d33fa..b969780e1 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -449,6 +449,7 @@ HEADERS_COMMON = \ common/owned_ptr.hpp \ common/owning_list.hpp \ common/pool.hpp \ + common/ptr_wrapper.hpp \ common/random.hpp \ common/random_manager.hpp \ common/retain_ptr.hpp \ diff --git a/src/core/common/owned_ptr.hpp b/src/core/common/owned_ptr.hpp index 88721b32d..f507e3dbe 100644 --- a/src/core/common/owned_ptr.hpp +++ b/src/core/common/owned_ptr.hpp @@ -36,8 +36,7 @@ #include "openthread-core-config.h" -#include -#include +#include "common/ptr_wrapper.hpp" namespace ot { @@ -52,17 +51,16 @@ namespace ot { * @tparam Type The pointer type. * */ -template class OwnedPtr +template class OwnedPtr : public Ptr { + using Ptr::mPointer; + public: /** * This is the default constructor for `OwnedPtr` initializing it as null. * */ - OwnedPtr(void) - : mPointer(nullptr) - { - } + OwnedPtr(void) = default; /** * This constructor initializes the `OwnedPtr` with a given pointer. @@ -73,7 +71,7 @@ public: * */ explicit OwnedPtr(Type *aPointer) - : mPointer(aPointer) + : Ptr(aPointer) { } @@ -99,31 +97,6 @@ public: */ ~OwnedPtr(void) { Delete(); } - /** - * This method indicates whether the `OwnedPtr` is null or not. - * - * @retval TRUE The `OwnedPtr` is null. - * @retval FALSE The `OwnedPtr` is not null. - * - */ - bool IsNull(void) const { return (mPointer == nullptr); } - - /** - * This method gets the raw pointer to the object owned by `OwnedPtr`. - * - * @returns The raw pointer to the object owned by `OwnedPtr` or `nullptr` if none. - * - */ - Type *Get(void) { return mPointer; } - - /** - * This method gets the raw pointer to the object owned by `OwnedPtr`. - * - * @returns The raw pointer to the object owned by `OwnedPtr` or `nullptr` if none. - * - */ - const Type *Get(void) const { return mPointer; } - /** * This method frees the owned object (if any). * @@ -171,42 +144,6 @@ public: return pointer; } - /** - * This method overloads the `->` dereference operator and returns a pointer to the object owned by `OwnedPtr`. - * - * @returns A pointer to owned object or `nullptr` if none. - * - */ - Type *operator->(void) { return mPointer; } - - /** - * This method overloads the `->` dereference operator and returns a pointer to the object owned by `OwnedPtr`. - * - * @returns A pointer to owned object or `nullptr` if none. - * - */ - const Type *operator->(void)const { return mPointer; } - - /** - * This method overloads the `*` dereference operator and returns a reference to the object owned by `OwnedPtr`. - * - * The behavior is undefined if `IsNull() == true`. - * - * @returns A reference to the object owned by `OwnedPtr`. - * - */ - Type &operator*(void) { return *mPointer; } - - /** - * This method overloads the `*` dereference operator and returns a reference to the object owned by `OwnedPtr`. - * - * The behavior is undefined if `IsNull() == true`. - * - * @returns A reference to the object owned by `OwnedPtr`. - * - */ - const Type &operator*(void)const { return *mPointer; } - /** * This method overload the assignment operator `=` to replace the object owned by the `OwnedPtr` with another one * using move semantics. @@ -238,8 +175,6 @@ private: mPointer->Free(); } } - - Type *mPointer; }; } // namespace ot diff --git a/src/core/common/ptr_wrapper.hpp b/src/core/common/ptr_wrapper.hpp new file mode 100644 index 000000000..916c65d4c --- /dev/null +++ b/src/core/common/ptr_wrapper.hpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes definitions for a pointer wrapper. + */ + +#ifndef PTR_WRAPPER_HPP_ +#define PTR_WRAPPER_HPP_ + +#include "openthread-core-config.h" + +#include +#include + +namespace ot { + +/** + * This template class represents a wrapper over a pointer. + * + * This is intended as base class of `OwnedPtr` or `RetainPtr` providing common simple methods. + * + * @tparam Type The pointer type. + * + */ +template class Ptr +{ +public: + /** + * This is the default constructor for `Ptr` initializing it as null. + * + */ + Ptr(void) + : mPointer(nullptr) + { + } + + /** + * This constructor initializes the `Ptr` with a given pointer. + * + * @param[in] aPointer A pointer to initialize with. + * + */ + explicit Ptr(Type *aPointer) + : mPointer(aPointer) + { + } + + /** + * This method indicates whether the `Ptr` is null or not. + * + * @retval TRUE The `Ptr` is null. + * @retval FALSE The `Ptr` is not null. + * + */ + bool IsNull(void) const { return (mPointer == nullptr); } + + /** + * This method gets the wrapped pointer. + * + * @returns The wrapped pointer. + * + */ + Type *Get(void) { return mPointer; } + + /** + * This method gets the wrapped pointer. + * + * @returns The wrapped pointer. + * + */ + const Type *Get(void) const { return mPointer; } + + /** + * This method overloads the `->` dereference operator and returns the pointer. + * + * @returns The wrapped pointer. + * + */ + Type *operator->(void) { return mPointer; } + + /** + * This method overloads the `->` dereference operator and returns the pointer. + * + * @returns The wrapped pointer. + * + */ + const Type *operator->(void)const { return mPointer; } + + /** + * This method overloads the `*` dereference operator and returns a reference to the pointed object. + * + * The behavior is undefined if `IsNull() == true`. + * + * @returns A reference to the pointed object. + * + */ + Type &operator*(void) { return *mPointer; } + + /** + * This method overloads the `*` dereference operator and returns a reference to the pointed object. + * + * The behavior is undefined if `IsNull() == true`. + * + * @returns A reference to the pointed object. + * + */ + const Type &operator*(void)const { return *mPointer; } + + /** + * This method overloads the operator `==` to compare the `Ptr` with a given pointer. + * + * @param[in] aPointer The pointer to compare with. + * + * @retval TRUE If `Ptr` is equal to @p aPointer. + * @retval FLASE If `Ptr` is not equal to @p aPointer. + * + */ + bool operator==(const Type *aPointer) const { return (mPointer == aPointer); } + + /** + * This method overloads the operator `!=` to compare the `Ptr` with a given pointer. + * + * @param[in] aPointer The pointer to compare with. + * + * @retval TRUE If `Ptr` is not equal to @p aPointer. + * @retval FLASE If `Ptr` is equal to @p aPointer. + * + */ + bool operator!=(const Type *aPointer) const { return (mPointer != aPointer); } + + /** + * This method overloads the operator `==` to compare the `Ptr` with another `Ptr`. + * + * @param[in] aOther The other `Ptr` to compare with. + * + * @retval TRUE If `Ptr` is equal to @p aOther. + * @retval FLASE If `Ptr` is not equal to @p aOther. + * + */ + bool operator==(const Ptr &aOther) const { return (mPointer == aOther.mPointer); } + + /** + * This method overloads the operator `!=` to compare the `Ptr` with another `Ptr`. + * + * @param[in] aOther The other `Ptr` to compare with. + * + * @retval TRUE If `Ptr` is not equal to @p aOther. + * @retval FLASE If `Ptr` is equal to @p aOther. + * + */ + bool operator!=(const Ptr &aOther) const { return (mPointer != aOther.mPointer); } + +protected: + Type *mPointer; +}; + +} // namespace ot + +#endif // PTR_WRAPPER_HPP_ diff --git a/src/core/common/retain_ptr.hpp b/src/core/common/retain_ptr.hpp index 81f6816da..5605ced58 100644 --- a/src/core/common/retain_ptr.hpp +++ b/src/core/common/retain_ptr.hpp @@ -36,8 +36,7 @@ #include "openthread-core-config.h" -#include -#include +#include "common/ptr_wrapper.hpp" namespace ot { @@ -56,17 +55,16 @@ namespace ot { * @tparam Type The pointer type. * */ -template class RetainPtr +template class RetainPtr : public Ptr { + using Ptr::mPointer; + public: /** * This is the default constructor for `RetainPtr` initializing it as null. * */ - RetainPtr(void) - : mPointer(nullptr) - { - } + RetainPtr(void) = default; /** * This constructor initializes the `RetainPtr` with a given pointer. @@ -77,7 +75,7 @@ public: * */ explicit RetainPtr(Type *aPointer) - : mPointer(aPointer) + : Ptr(aPointer) { IncrementRetainCount(); } @@ -89,7 +87,7 @@ public: * */ RetainPtr(const RetainPtr &aOther) - : mPointer(aOther.mPointer) + : Ptr(aOther.mPointer) { IncrementRetainCount(); } @@ -103,31 +101,6 @@ public: */ ~RetainPtr(void) { DecrementRetainCount(); } - /** - * This method indicates whether the `RetainPtr` is null or not. - * - * @retval TRUE The `RetainPtr` is null. - * @retval FALSE The `RetainPtr` is not null. - * - */ - bool IsNull(void) const { return (mPointer == nullptr); } - - /** - * This method gets the raw pointer to the object managed by `RetainPtr`. - * - * @returns The raw pointer to the object managed by `RetainPtr` or `nullptr` if none. - * - */ - Type *Get(void) { return mPointer; } - - /** - * This method gets the raw pointer to the object managed by `RetainPtr`. - * - * @returns The raw pointer to the object managed by `RetainPtr` or `nullptr` if none. - * - */ - const Type *Get(void) const { return mPointer; } - /** * This method replaces the managed object by `RetainPtr` with a new one. * @@ -164,56 +137,20 @@ public: } /** - * This method overloads the `->` dereference operator and returns a pointer to the object managed by `RetainPtr`. - * - * @returns A pointer to managed object or `nullptr` if none. - * - */ - Type *operator->(void) { return mPointer; } - - /** - * This method overloads the `->` dereference operator and returns a pointer to the object managed by `RetainPtr`. - * - * @returns A pointer to managed object or `nullptr` if none. - * - */ - const Type *operator->(void)const { return mPointer; } - - /** - * This method overloads the `*` dereference operator and returns a reference to the object managed by `RetainPtr`. - * - * The behavior is undefined if `IsNull() == true`. - * - * @returns A reference to the object managed by `RetainPtr`. - * - */ - Type &operator*(void) { return *mPointer; } - - /** - * This method overloads the `*` dereference operator and returns a reference to the object managed by `RetainPtr`. - * - * The behavior is undefined if `IsNull() == true`. - * - * @returns A reference to the object managed by `RetainPtr`. - * - */ - const Type &operator*(void)const { return *mPointer; } - - /** - * This method overload assignment operator `=` . + * This method overloads the assignment operator `=`. * * The `RetainPtr` first frees its current managed object (if there is any and it is different from @p aOther) * before taking over the ownership of the object from @p aOther. This method correctly handles a self assignment * (i.e., assigning the pointer to itself). * - * @param[in] aOther A reference to an `OwendPtr`. + * @param[in] aOther A reference to another `RetainPtr`. * * @returns A reference to this `RetainPtr`. * */ - RetainPtr &operator=(RetainPtr &aOther) + RetainPtr &operator=(const RetainPtr &aOther) { - Reset(aOther.Get()); + Reset(aOther.mPointer); return *this; } @@ -233,8 +170,6 @@ private: mPointer->Free(); } } - - Type *mPointer; }; /** diff --git a/tests/unit/test_smart_ptrs.cpp b/tests/unit/test_smart_ptrs.cpp index 5ca1c2b3f..a892d1cfa 100644 --- a/tests/unit/test_smart_ptrs.cpp +++ b/tests/unit/test_smart_ptrs.cpp @@ -67,11 +67,14 @@ void VerifyPointer(const PointerType &aPointer, { VerifyOrQuit(aPointer.IsNull()); VerifyOrQuit(aPointer.Get() == nullptr); + VerifyOrQuit(aPointer == nullptr); } else { VerifyOrQuit(!aPointer.IsNull()); VerifyOrQuit(aPointer.Get() == aObject); + VerifyOrQuit(aPointer == aObject); + VerifyOrQuit(aPointer != nullptr); VerifyOrQuit(!aPointer->WasFreed()); VerifyOrQuit(!(*aPointer).WasFreed()); @@ -81,6 +84,8 @@ void VerifyPointer(const PointerType &aPointer, VerifyOrQuit(aObject->GetRetainCount() == aRetainCount); } } + + VerifyOrQuit(aPointer == aPointer); } void TestOwnedPtr(void) @@ -388,27 +393,35 @@ void TestRetainPtr(void) VerifyPointer(ptr2, &obj2, 1); VerifyPointer(ptr3, nullptr); + VerifyOrQuit(ptr1 != ptr2); + VerifyOrQuit(ptr1 != ptr3); + VerifyOrQuit(ptr2 != ptr3); + // Set from non-null (ptr1) to non-null (ptr2) ptr2 = ptr1; VerifyPointer(ptr1, &obj1, 2); VerifyPointer(ptr2, &obj1, 2); VerifyOrQuit(obj2.WasFreed()); + VerifyOrQuit(ptr1 == ptr2); // Set from null (ptr3) to non-null (ptr1) ptr1 = ptr3; VerifyPointer(ptr1, nullptr); VerifyPointer(ptr3, nullptr); VerifyPointer(ptr2, &obj1, 1); + VerifyOrQuit(ptr1 == ptr3); // Move from null (ptr1) to null (ptr3) ptr3 = ptr1; VerifyPointer(ptr1, nullptr); VerifyPointer(ptr3, nullptr); + VerifyOrQuit(ptr1 == ptr3); // Move from non-null (ptr2) to null (ptr3) ptr3 = ptr2; VerifyPointer(ptr2, &obj1, 2); VerifyPointer(ptr3, &obj1, 2); + VerifyOrQuit(ptr2 == ptr3); } VerifyOrQuit(obj1.WasFreed());