[common] add Ptr to use as base of OwnedPtr and RetainPtr (#7195)

This commit adds a new class `Ptr<Type>` which represents a wrapper
over a raw pointer. This is then used as the base class of `OwnedPtr`
and `RetainPtr` providing the common simple methods (avoiding repeating
the same code in each smart pointter). The new `Ptr` class also adds
overloads of `==` and `!=` allowing `Ptr` to be compared with a given
raw pointer or another `Ptr` instance.
This commit is contained in:
Abtin Keshavarzian
2021-11-24 21:14:49 -08:00
committed by Jonathan Hui
parent 2d16fa25e4
commit 4acdf1d0fb
6 changed files with 218 additions and 147 deletions
+1
View File
@@ -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",
+1
View File
@@ -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 \
+6 -71
View File
@@ -36,8 +36,7 @@
#include "openthread-core-config.h"
#include <stdbool.h>
#include <stdint.h>
#include "common/ptr_wrapper.hpp"
namespace ot {
@@ -52,17 +51,16 @@ namespace ot {
* @tparam Type The pointer type.
*
*/
template <class Type> class OwnedPtr
template <class Type> class OwnedPtr : public Ptr<Type>
{
using Ptr<Type>::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<Type>(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
+186
View File
@@ -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 <stdbool.h>
#include <stdint.h>
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 Type> 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_
+11 -76
View File
@@ -36,8 +36,7 @@
#include "openthread-core-config.h"
#include <stdbool.h>
#include <stdint.h>
#include "common/ptr_wrapper.hpp"
namespace ot {
@@ -56,17 +55,16 @@ namespace ot {
* @tparam Type The pointer type.
*
*/
template <class Type> class RetainPtr
template <class Type> class RetainPtr : public Ptr<Type>
{
using Ptr<Type>::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<Type>(aPointer)
{
IncrementRetainCount();
}
@@ -89,7 +87,7 @@ public:
*
*/
RetainPtr(const RetainPtr &aOther)
: mPointer(aOther.mPointer)
: Ptr<Type>(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;
};
/**
+13
View File
@@ -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());