* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* @file refbase.h
*
* @brief Provide smart pointer implemented in c_utils.
*/
* @defgroup SmartPointer
* @{
* @brief Smart Pointer are pointer-like classes.
*
* They simulates a pointer while providing added features,
* such as automatic memory management.\n
* Automatic memory management is mainly about deallocating
* the related memory correctly when an object beyonds its life cycle.
*/
#ifndef UTILS_BASE_REFBASE_H
#define UTILS_BASE_REFBASE_H
#include <atomic>
#include <functional>
#ifdef DEBUG_REFBASE
#include <mutex>
#endif
#ifdef _WIN32
#define RS_EXPORT __attribute__((dllexport))
#else
#define RS_EXPORT __attribute__((visibility("default")))
#endif
namespace OHOS {
* @ingroup SmartPointer
* @brief A value indicates no strong references exist ever.
*/
#define INITIAL_PRIMARY_VALUE (1 << 28)
class RefBase;
#ifdef DEBUG_REFBASE
class RefTracker;
#endif
* @ingroup SmartPointer
* @brief Reference counter. A class records two kinds of count of references to
* the corresponding RefBase object, and a count of references to the RefCounter
* itself.
*
* There are two different references for a single object.\n
* Strong Reference holds a reference directly point to the object.
* Objects which are strong referenced ought to be alive/existed
* as long as this strong reference exists, thus the reference
* is still valid.\n
* Weak Reference holds a reference indirectly point to the object.
* Objects which are weak referenced are not guaranteed to be alive/existed
* even if the weak reference exists.
* @note Descriptions above are valid only when smart pointers
* are properly used.
*/
class RefCounter {
public:
* @brief Callback function to destroy the corresponding RefBase object.
*/
using RefPtrCallback = std::function<void()>;
friend class RefBase;
RefCounter();
explicit RefCounter(RefCounter *counter);
RefCounter &operator=(const RefCounter &counter);
virtual ~RefCounter();
* @brief Set the callback function.
*
* @param callback A function to be set to delete
* the corresponding RefBase object.
*/
void SetCallback(const RefPtrCallback& callback);
* @brief Remove the current callback function. Set it to a `nullptr`.
*/
void RemoveCallback();
* @brief Get reference count to the RefCounter object.
*
* @return Value of the related count.
*/
int GetRefCount();
* @brief Increment the reference count to the RefCounter object by 1.
*/
void IncRefCount();
* @brief Decrement the reference count to the RefCounter object by 1.
*
* Once the count reaches 0 after being decremented,
* it will call `delete this` to deallocate this RefCounter object.
*/
void DecRefCount();
* @brief Check if pointer to the call back function is a `nullptr`.
*
* @return Return true if it is not a `nullptr`.
*/
bool IsRefPtrValid();
* @brief Increment the strong reference count to the
* corresponding RefBase object by 1.
*
* @return Original (before increment) value of the count.
*/
int IncStrongRefCount(const void *objectId);
* @brief Decrement the strong reference count to the
* corresponding RefBase object by 1.
*
* @return Original (before decrement) value of the count.
* @note If the strong reference has never existed,
* decrement will cause no effection.
*/
int DecStrongRefCount(const void *objectId);
* @brief Get the strong reference count to the
* corresponding RefBase object.
*
* @return Value of the related count.
*/
int GetStrongRefCount();
* @brief Increment the weak reference count to the
* corresponding RefBase object by 1.
*
* @return Original (before increment) value of the count.
*/
int IncWeakRefCount(const void *objectId);
* @brief Decrement the weak reference count to the
* corresponding RefBase object by 1.
*
* @return Original (before decrement) value of atomicWeak_.
* @note When the count reaches 0 after being decremented, the
* corresponding RefBase object with no strong reference ever,
* or the object with strong reference count of 0 but has not been
* deallocated due to its extended 'life time', will be deallocated.
*/
int DecWeakRefCount(const void *objectId);
* @brief Get the weak reference count to the
* corresponding RefBase object.
*
* @return Value of the related count.
*/
int GetWeakRefCount();
* @brief Increment the times of attempts to increment.
*/
void SetAttemptAcquire();
* @brief Check if the times of attempts greater than 0.
*
* @return Return true if the times is greater than 0.
*/
bool IsAttemptAcquireSet();
* @brief Clear the times of attempts to increment.
*/
void ClearAttemptAcquire();
* @brief Attempt to increment the strong reference count to the
* corresponding RefBase object by 1.
*
* @param outCount If the attempt success, the original value
* (before increment) of the count will be stored here.
* @return Return true if the attempt success.
*/
bool AttemptIncStrongRef(const void *objectId, int &outCount);
* @brief Attempt to increment the strong reference count to
* the corresponding RefBase object by 1(Simplified).
*
* @return Return true if the attempt success.
* @note Ony for IPC use.
*/
bool AttemptIncStrong(const void *objectId);
* @brief Check if the corresponding RefBase object
* own an extended life-time.
*
* @return Return true if its life-time has been extended.
*/
bool IsLifeTimeExtended();
* @brief Extend the life-time of corresponding RefBase object.
*
* It allows the corresponding object keep alive
* even if there exists no strong reference to it.
* @note Corresponding object will be deallocated
* when related weak reference count also reach 0.
*/
void ExtendObjectLifetime();
private:
std::atomic<int> atomicStrong_;
std::atomic<int> atomicWeak_;
std::atomic<int> atomicRefCount_;
std::atomic<unsigned int> atomicFlags_;
std::atomic<int> atomicAttempt_;
RefPtrCallback callback_ = nullptr;
static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002;
#ifdef DEBUG_REFBASE
RefTracker* refTracker = nullptr;
std::mutex trackerMutex;
void GetNewTrace(const void* objectId);
void PrintTracker();
#endif
};
#ifdef DEBUG_REFBASE
class RefTracker {
public:
RefTracker() {};
RefTracker(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
void GetTrace(RefTracker* exTracker, const void* id, int strong, int weak, int ref, int pid, int tid);
void GetStrongTrace(RefTracker* exTracker, const void* id, int strong, int pid, int tid);
void GetWeakTrace(RefTracker* exTracker, const void* id, int weak, int pid, int tid);
void PrintTrace(const void* root);
void PrintStrongTrace(const void* root);
void PrintWeakTrace(const void* root);
RefTracker* GetexTrace();
RefTracker* PopTrace(const void* root);
private:
const void* ptrID;
int strongRefCNT;
int weakRefCNT;
int refCNT;
int PID;
int TID;
RefTracker* exTrace;
};
#endif
* @ingroup SmartPointer
* @brief An intermediate class to represent the weak reference
* to the correspond RefBase object.
*
* A WeakRefCounter object can be held by multiple wptr objects.\n
* It holds references to the corresponding RefBase and RefCounter object.
* Those two references will be set as `nullptr`s, when the weak referenced
* target and its RefCounter object has been deallocated. Thus WeakRefCounter
* object can still alive even if the target refereneced by this object
* is vanished.
*/
class WeakRefCounter {
public:
* @brief Construct a new Weak Ref Counter object.
*
* @param counter Pointer to corresponding RefCounter object.
* @param cookie Pointer to corresponding RefBase object.
*/
WeakRefCounter(RefCounter *counter, void *cookie);
virtual ~WeakRefCounter();
* @brief Get current pointer to the corresponding RefBase object.
*
* @return A void pointer to the RefBase object.
* If the corresponding object does not alive, a `nullptr` will return.
* @note Void pointer means you should cast it to the real type, since it
* can be kinds of subclasses of RefBase.
*/
void *GetRefPtr();
* @brief Increment the reference count to this WeakRefCounter object.
*
* @note Notice the difference between this count and the weak reference
* count in RefCounter. This value equals to the number of wptrs directly
* referencing this WeakRefCount object.
* @see RefCounter
*/
void IncWeakRefCount(const void *objectId);
* @brief Decrement the reference count to this WeakRefCounter object.
*
* @note This WeakRefCounter object will be deallocated when this count
* reaches 0.
*/
void DecWeakRefCount(const void *objectId);
* @brief Get the count recorded by this WeakRefCounter object.
*
* @return Value of the count.
* @note This value of count is different from that in RefCounter.
* @see RefCounter::GetWeakRefCount()
*/
int GetWeakRefCount() const;
* @brief Attempt to increment the strong reference count of
* the corresponding RefBase object(Used in promoting a wptr to a sptr).
*
* @return Return `true` after a success increment.
*/
bool AttemptIncStrongRef(const void *objectId);
private:
std::atomic<int> atomicWeak_;
RefCounter *refCounter_ = nullptr;
void *cookie_ = nullptr;
};
* @ingroup SmartPointer
* @brief A base class which can be managed by a smart pointer.
*
* @note All classes which intend to be managed by smart pointers should be
* derived from RefBase.
*/
class RS_EXPORT RefBase {
public:
RefBase();
* @brief Copy constructor of RefBase.
*
* @note Note that this method will construct a new RefCounter object,
* and bind with it.
*/
RefBase(const RefBase &);
* @brief Copy assignment operator of RefBase.
*
* @note This method will unbind the current RefBase object and its
* original RefCounter object, then bind a newly constructed
* RefCounter object.
*/
RefBase &operator=(const RefBase &);
* @brief Move constructor of RefBase.
*/
RefBase(RefBase &&other) noexcept;
* @brief Move assignment operator of RefBase.
*
* @note This method will bind this RefBase object with the RefCounter
* object of the argument `other`, then `other` will unbind the RefCounter
* object.\n No counts operation will be poccessed.
*/
RefBase &operator=(RefBase &&other) noexcept;
virtual ~RefBase();
* @brief A callback method to deallocate this object.
*
* This method has default implement to simply deallocate this RefBase
* object simply by calling `delete(this)`.
*/
virtual void RefPtrCallback();
* @brief Extend life time of the RefBase object.
*
* @note The object whose life time has been extended will not be
* deallocated when the the weak reference count reach 0 instead of the
* strong one.
*/
void ExtendObjectLifetime();
* @brief Increment the strong reference count.
*
* `OnFirstStrongRef()`, which is an empty method by default, will be
* called when the first strong reference are established.、
*
* @note It will atomically increment the weak reference count meanwhile.
*/
void IncStrongRef(const void *objectId);
* @brief Decrement the strong reference count.
*
* This object will be deallocated when the count reaches 0, if it owns a
* normal life time.\n `OnLastStrongRef()`, which is an empty method by
* default, will be called when the last strong reference vanishes.
*/
void DecStrongRef(const void *objectId);
* @brief Get the strong reference count.
*
* @return Related count value. Return 0 when corresponding RefCounter
* object does not exist.
* @note Only valid when corresponding RefCounter object exists.
*/
int GetSptrRefCount();
* @brief Create weak reference to this RefBase object.
*
* Create a WeakRefCounter object which holds reference to this RefBase
* object and set the reference count.
*
* @param cookie Void pointer to this RefBase object.
* @return Pointer to the newly created WeakRefCounter object.
* @note Avoid using it independently. Use related methods of wptr.
*/
WeakRefCounter *CreateWeakRef(void *cookie);
* @brief Get the pointer to corresponding counter object.
*
* @return Pointer to the counter object.
*/
RefCounter *GetRefCounter() const;
* @brief Increment the weak reference count.
*
* @note Only valid when corresponding RefCounter object exists.
*/
void IncWeakRef(const void *objectId);
* @brief Decrement the weak reference count.
*
* @note Only valid when corresponding RefCounter object exists.
*/
void DecWeakRef(const void *objectId);
* @brief Get the weak reference count.
*
* @return Value of related count. Return 0 when corresponding
* RefCounter object doesn't exist.
*/
int GetWptrRefCount();
* @brief Attempt to increment the strong reference count.
*
* `OnFirstStrongRef()`, which is an empty method by default, will be
* called when the first strong reference are established.
*
* @return Return true if successfully increment the count.
* @note Note that count of times of attempts will increment by 1
* after a successful increment.
*/
bool AttemptAcquire(const void *objectId);
* @brief Attempt to increment the strong reference count.
*
* `OnFirstStrongRef()`, which is an empty method by default, will be
* called when the first strong reference are established.
* @return Return true if successfully increment the count.
* @note Used in various copy constructor of sptr in scenario of
* interaction between sptr and wptr. Avoid using it independently.
*/
bool AttemptIncStrongRef(const void *objectId);
* @brief Attempt to increment the strong reference count.
*
* @return Return true if successfully increment the count, otherwise
* return false.
* @note Note that times of successful attempts will increment by 1 after
* a successful increment of the related count.
* @note This method is a simplified version of `AttemptAcquire`, but only
* for IPC use.
*/
bool AttemptIncStrong(const void *objectId);
* @brief check if the times of successful attempts of greater than 0.
*
* @return Return true if times of successful attempts is greater than 0;
* Return false if it is not greater than 0, or the corresponding
* RefCounter object does not exist.
*/
bool IsAttemptAcquireSet();
* @brief Check if the life time of this RefBase object has been extended.
*
* @return Return false when have a normal life time, or the corresponding
* RefCounter object does not exist.
*/
bool IsExtendLifeTimeSet();
* @brief An event-drive method, which will be automatically called when
* first strong reference comes up.
*
* @note It is an empty function by default.
*/
virtual void OnFirstStrongRef(const void *);
* @brief An event-drive method, which will be automatically called when
* last strong reference eliminates.
*
* @note It is an empty function by default.
*/
virtual void OnLastStrongRef(const void *);
* @brief An event-drive method, which will be automatically called when
* last weak reference eliminates.
*
* @note It is an empty function by default.
*/
virtual void OnLastWeakRef(const void *);
* @brief An event-drive method, which will be autmatically called when
* use `wptr::Promote()`.
*
* @note Directly return true by default.
* @return Return true if success, otherwise return false.
*/
virtual bool OnAttemptPromoted(const void *);
private:
RefCounter *refs_ = nullptr;
};
template <typename T>
class wptr;
* @ingroup SmartPointer
* @brief Strong reference smart pointer to a RefBase(or its subclass) object.
*
* It directly reference the RefBase object.
*
* @tparam T Specific class type managed by sptr. This class must inherit
* from RefBase.
*/
template <typename T>
class sptr {
friend class wptr<T>;
public:
sptr();
~sptr();
* @brief Constructor with specified object to be managed.
*
* @note Null sptr will be created if `other` is a `nullptr`.
* @param other Object to be managed by wptr.
*/
sptr(T *other);
* @brief Copy Constructor for sptr with different managed class type(T).
*
* @param other Input sptr object.
*/
sptr(const sptr<T> &other);
* @brief Move constructor.
*
* @note `other` will be set to a null sptr.
* @param other Input sptr object.
*/
sptr(sptr<T> &&other);
* @brief Move assignment operator.
*
* @param other Input sptr object.
* @note Original strong reference in target sptr object will be removed.
*/
sptr<T> &operator=(sptr<T> &&other);
* @brief Copy Constructor for sptr with different managed class type(O).
*
* @tparam O Another specific class type managed by `other`.
* @param other Input sptr object.
*/
template <typename O>
sptr(const sptr<O> &other);
* @brief Constructor only used in promote process of wptr.
*
* @param p WeakRefCounter object which hold the reference to the
* managed object.
* @param force Only used to identify from other constructor.
*/
inline sptr(WeakRefCounter *p, bool force);
* @brief Get the pointer to the managed object.
*
* @return Pointer of the specific managed class type.
*/
inline T *GetRefPtr() const
{
return refs_;
}
* @brief Set the pointer to the managed object.
*
* @param other Another pointer object to be managed by sptr.
* @note Avoid using independently, otherwise it will
* cause mismatch of reference count and thus memory problems.
*/
inline void ForceSetRefPtr(T *other);
* @brief Remove the reference to the managed object held by current sptr.
*
* @note It will make this sptr a "null sptr".
*/
void clear();
* @brief Type conversion operator.
*
* @return Raw pointer to the managed object.
* @note Sptr object itself will not be converted, only the member raw
* pointer returns.
*/
inline operator T *() const
{
return refs_;
}
* @brief Dereference operator.
*
* It will return the object managed by this sptr.
*
* @return Return reference of specific object managed by sptr.
*/
inline T &operator*() const
{
return *refs_;
}
* @brief Member selection operator.
*
* It will return the specified member of the object managed by this sptr.
*/
inline T *operator->() const
{
return refs_;
}
* @brief Logical-NOT operator. Check if sptr is a "null sptr".
*
* @return Return true if sptr is a "null sptr".
*/
inline bool operator!() const
{
return refs_ == nullptr;
}
* @brief Copy assignment operator with specified object to be managed.
*
* @note Original reference will be removed, then new reference to the
* input object will be established.
* @param other Another object to be managed by this sptr.
*/
sptr<T> &operator=(T *other);
* @brief Copy assignment operator for sptr with
* same managed class type(T).
*
* @note Original reference will be removed, this sptr will manage the
* same object with the input sptr object.
* @param other Another sptr object with same managed class type(T).
*/
sptr<T> &operator=(const sptr<T> &other);
* @brief Copy assignment operator for wptr with
* same managed class type(T).
*
* @note Original reference will be removed, this sptr will manage the
* same object with the input wptr object.
* @note This may fail, then this sptr will turn to be a "null sptr".
* @param other Another wptr object with same managed class type(T).
*/
sptr<T> &operator=(const wptr<T> &other);
* @brief Copy assignment operator for sptr with
* different managed class type(O).
*
* @note Original reference will be removed, this sptr will manage the
* same object with the input sptr object.
* @note This sptr will interpret the managed object as a type T.
* @param other Another sptr object with different managed class type(O).
*/
template <typename O>
sptr<T> &operator=(const sptr<O> &other);
* @brief Equal-to operator between sptr and a raw pointer.
*
* @param other Input raw pointer.
* @return Return true if sptr point to the same object with input
* raw pointer.
*/
bool operator==(const T *other) const;
* @brief Not-equal-to operator between sptr and a raw pointer.
*
* @param other Input raw pointer.
* @return Return true if sptr does not point to the same object with input
* raw pointer.
*/
inline bool operator!=(const T *other) const
{
return !operator==(other);
}
* @brief Equal-to operator between sptr and a wptr.
*
* @param other Input wptr.
* @return Return true if sptr and wptr are managing same object.
*/
bool operator==(const wptr<T> &other) const;
* @brief Not-equal-to operator between sptr and a wptr.
*
* @param other Input wptr.
* @return Return true if sptr and wptr are not managing same object.
*/
inline bool operator!=(const wptr<T> &other) const
{
return !operator==(other);
}
* @brief Equal-to operator between sptrs.
*
* @param other Input sptr.
* @return Return true if two sptrs are managing same object.
*/
bool operator==(const sptr<T> &other) const;
* @brief Not-equal-to operator between sptrs.
*
* @param other Input sptr.
* @return Return true if two sptrs are not managing same object.
*/
inline bool operator!=(const sptr<T> &other) const
{
return !operator==(other);
}
private:
T *refs_ = nullptr;
};
template <typename T>
inline void sptr<T>::ForceSetRefPtr(T *other)
{
refs_ = other;
}
template <typename T>
inline sptr<T>::sptr()
{
refs_ = nullptr;
}
template <typename T>
inline sptr<T>::sptr(T *other)
{
refs_ = other;
if (refs_ != nullptr) {
refs_->IncStrongRef(this);
}
}
template <typename T>
inline sptr<T>::sptr(const sptr<T> &other)
{
refs_ = other.GetRefPtr();
if (refs_ != nullptr) {
refs_->IncStrongRef(this);
}
}
template <typename T>
sptr<T>::sptr(sptr<T> &&other)
{
refs_ = other.GetRefPtr();
other.ForceSetRefPtr(nullptr);
}
template <typename T>
sptr<T> &sptr<T>::operator=(sptr<T> &&other)
{
if (refs_ != nullptr) {
refs_->DecStrongRef(this);
}
refs_ = other.GetRefPtr();
other.ForceSetRefPtr(nullptr);
return *this;
}
template <typename T>
template <typename O>
sptr<T>::sptr(const sptr<O> &other) : refs_(other.GetRefPtr())
{
if (refs_ != nullptr) {
refs_->IncStrongRef(this);
}
}
template <typename T>
inline sptr<T> &sptr<T>::operator=(T *other)
{
if (other != nullptr) {
other->IncStrongRef(this);
}
if (refs_ != nullptr) {
refs_->DecStrongRef(this);
}
refs_ = other;
return *this;
}
template <typename T>
inline sptr<T> &sptr<T>::operator=(const sptr<T> &other)
{
T *otherRef(other.GetRefPtr());
if (otherRef != nullptr) {
otherRef->IncStrongRef(this);
}
if (refs_ != nullptr) {
refs_->DecStrongRef(this);
}
refs_ = otherRef;
return *this;
}
template <typename T>
inline sptr<T> &sptr<T>::operator=(const wptr<T> &other)
{
if (refs_ != nullptr) {
refs_->DecStrongRef(this);
}
if ((other != nullptr) && other.AttemptIncStrongRef(this)) {
refs_ = other.GetRefPtr();
} else {
refs_ = nullptr;
}
return *this;
}
template <typename T>
template <typename O>
sptr<T> &sptr<T>::operator=(const sptr<O> &other)
{
T *otherRef(other.GetRefPtr());
if (otherRef != nullptr) {
otherRef->IncStrongRef(this);
}
if (refs_ != nullptr) {
refs_->DecStrongRef(this);
}
refs_ = otherRef;
return *this;
}
template <typename T>
inline bool sptr<T>::operator==(const T *other) const
{
return other == refs_;
}
template <typename T>
inline bool sptr<T>::operator==(const wptr<T> &other) const
{
return refs_ == other.GetRefPtr();
}
template <typename T>
inline bool sptr<T>::operator==(const sptr<T> &other) const
{
return refs_ == other.GetRefPtr();
}
template<typename T>
void sptr<T>::clear()
{
if (refs_) {
refs_->DecStrongRef(this);
refs_ = 0;
}
}
template <typename T>
inline sptr<T>::~sptr()
{
if (refs_ != nullptr) {
refs_->DecStrongRef(this);
}
}
template <typename T>
inline sptr<T>::sptr(WeakRefCounter *p, bool )
{
if ((p != nullptr) && p->AttemptIncStrongRef(this)) {
refs_ = reinterpret_cast<T *>(p->GetRefPtr());
} else {
refs_ = nullptr;
}
}
* @ingroup SmartPointer
* @brief Weak reference smart pointer to a RefBase(or its subclass) object.
*
* Indirectly reference the RefBase object;
* Directly reference the WeakRefCounter object.
*
* @tparam T Specific class type managed by wptr.
* This class must inherit from RefBase.
*/
template <typename T>
class wptr {
template <typename O>
friend class wptr;
public:
wptr();
* @brief Constructor with specified object to be managed.
*
* This method will create WeakRefCounter object for `other` and set its
* weak reference count to 1.
*
* @note WeakRefCounter object will not be created if `other` is a
* `nullptr`.
* @param other Object to be managed by wptr.
*/
wptr(T *other);
* @brief Copy constructor for wptr with same managed class type(T).
*
* This method will share the WeakRefCounter object of `other` with this
* wptr. Weak reference count in this WeakRefCounter object will be set
* properly.
*
* @param other Another wptr with same managed class type(T).
*/
wptr(const wptr<T> &other);
* @brief Copy constructor for sptr with same managed class type(T).
*
* This method will create WeakRefCounter object for the managed object of
* `other`, and set its weak reference count properly.
*
* @param other Another sptr with same managed class type(T).
* @tparam T Specific class type managed by `other`.
*/
wptr(const sptr<T> &other);
* @brief Copy constructor for wptr with different managed class type(O).
*
* Same with wptr<T>::wptr(const wptr<T> &other).
*
* @tparam O Class type managed by `other`.
* @param other Another wptr with different managed class type(O).
* @tparam T Specific class type managed by `other`.
*/
template <typename O>
wptr(const wptr<O> &other);
* @brief Copy constructor for sptr with different managed class type(O).
*
* Same with wptr<T>::wptr(const sptr<T> &other).
*
* @param other Another sptr with same managed class type(O).
* @tparam T Specific class type managed by `other`.
*/
template <typename O>
wptr(const sptr<O> &other);
* @brief Copy assignment operator with specified object to be managed.
*
* @note Current wptr will unbind the original WeakRefCounter object and
* create a new WeakRefCounter object, then set its weak reference count
* properly.
* @param other Another object to be managed by this wptr.
*/
wptr<T> &operator=(T *other);
* @brief Copy assignment operator with specified object to be managed.
*
* @note Same with wptr<T> &operator=(T *other), but a pointer type casting
* which will not affect the type of `*other` is proccessed.
* @tparam O Specific class type managed by `other`.
* @param other Another object to be managed by this wptr.
*
*/
template <typename O>
wptr<T> &operator=(O *other);
* @brief Copy assignment operator for wptr with same managed class type(T).
*
* @note Current wptr will unbind the original WeakRefCounter object and
* share the WeakRefCounter object with `other`, then set its weak
* reference count properly.
* @param other Another wptr. Object managed by it will also be managed by
* this wptr.
*/
wptr<T> &operator=(const wptr<T> &other);
* @brief Copy assignment operator for sptr with
* same managed class type(T).
*
* @note Current wptr will unbind the original WeakRefCounter object and
* create a new WeakRefCounter object, then set its weak reference count
* properly.
* @param other A sptr object. Object managed by it will also be managed by
* this wptr.
*/
wptr<T> &operator=(const sptr<T> &other);
* @brief Copy assignment operator for wptr with
* different managed class type(O).
*
* @note Same with wptr<T> &operator=(const wptr<T> &). Note that no cast
* here is proccessed.
* @param other An wptr object. Object managed by it will also be managed by
* this wptr.
* @tparam O Specific class type managed by `other`.
*/
template <typename O>
wptr<T> &operator=(const wptr<O> &other);
* @brief Copy assignment operator for sptr with
* different managed class type(O).
*
* @note Same with wptr<T> &wptr<T>::operator=(const sptr<T> &). Note that
* no cast here is proccessed.
* @param other An sptr object. Object managed by it will also be managed by
* this wptr.
* @tparam O Specific class type managed by `other`.
*/
template <typename O>
wptr<T> &operator=(const sptr<O> &other);
* @brief Dereference operator. It will return the object managed by this
* wptr.
*
* @return Return specific object managed by wptr.
*/
inline T &operator*() const
{
return *GetRefPtr();
}
* @brief Member selection operator.
*
* It will return the specified member of the object managed by this wptr.
*/
inline T *operator->() const
{
return reinterpret_cast<T *>(refs_->GetRefPtr());
}
* @brief Equal-to operator between wptr and a raw pointer.
*
* @param other Input raw pointer.
* @return Return true if two pointers have same value.
*/
bool operator==(const T *other) const;
* @brief Not-equal-to operator between wptr and a raw pointer.
*
* @param other Input raw pointer.
* @return Return true if two pointers have different value.
*/
inline bool operator!=(const T *other) const
{
return !operator==(other);
};
* @brief Equal-to operator between two wptrs.
*
* @param other Input reference of a wptr object.
* @return Return if two pointers have same value.
*/
bool operator==(const wptr<T> &other) const;
* @brief Not-equal-to operator between two wptrs.
*
* @param other Input reference of a wptr object.
* @return Return if two pointers have different value.
*/
inline bool operator!=(const wptr<T> &other) const
{
return !operator==(other);
}
* @brief Equal-to operator between wptr and a input sptr object.
*
* @param other Input reference of an sptr object.
* @return Comparison result.
*/
bool operator==(const sptr<T> &other) const;
* @brief Not-Equal-to operator between wptr and a input sptr object.
*
* @param other Input reference of an sptr object.
* @return Comparison result.
*/
inline bool operator!=(const sptr<T> &other) const
{
return !operator==(other);
}
* @brief Get the pointer to the RefBase object.
*
* @return Raw pointer to the RefBase object.
* @note Return `nullptr` if the managed object has been deallocated.
*/
T *GetRefPtr() const;
* @brief Get the count value of corresponding WeakRefCounter object.
*
* The value indicates how many wptrs share the same WeakRefCounter object.
*
* @return Value of the count.
* @note Only for test.
*/
inline int GetWeakRefCount() const
{
return refs_->GetWeakRefCount();
}
* @brief Attempt to increment the strong reference count of
* the managed object.
*
* @return Return true after a success increment.
* @note Avoid using it independently. Use `promote()`.
*/
inline bool AttemptIncStrongRef(const void *objectId) const
{
return refs_->AttemptIncStrongRef(objectId);
}
* @brief Promote a wptr to an sptr.
*
* It will create an sptr object based on
* object managed by this wptr.
*
* @note Original weak reference will be retained. Promote may fail,
* and then return a "null sptr".
*/
const sptr<T> promote() const;
~wptr();
private:
WeakRefCounter *refs_ = nullptr;
};
template <typename T>
inline T *wptr<T>::GetRefPtr() const
{
return (refs_ != nullptr) ? reinterpret_cast<T *>(refs_->GetRefPtr()) : nullptr;
}
template <typename T>
wptr<T>::wptr()
{
refs_ = nullptr;
}
template <typename T>
wptr<T>::wptr(T *other)
{
if (other != nullptr) {
refs_ = other->CreateWeakRef(other);
if (refs_ != nullptr) {
refs_->IncWeakRefCount(this);
}
} else {
refs_ = nullptr;
}
}
template <typename T>
wptr<T>::wptr(const wptr<T> &other)
{
refs_ = other.refs_;
if (refs_ != nullptr) {
refs_->IncWeakRefCount(this);
}
}
template <typename T>
wptr<T>::wptr(const sptr<T> &other)
{
if (other.GetRefPtr() != nullptr) {
refs_ = other->CreateWeakRef(other.GetRefPtr());
if (refs_ != nullptr) {
refs_->IncWeakRefCount(this);
}
}
}
template <typename T>
template <typename O>
wptr<T>::wptr(const wptr<O> &other)
{
refs_ = other.refs_;
if (refs_ != nullptr) {
refs_->IncWeakRefCount(this);
}
}
template <typename T>
template <typename O>
wptr<T>::wptr(const sptr<O> &other)
{
if (other.GetRefPtr() != nullptr) {
refs_ = other->CreateWeakRef(other.GetRefPtr());
if (refs_ != nullptr) {
refs_->IncWeakRefCount(this);
}
}
}
template <typename T>
wptr<T> &wptr<T>::operator=(T *other)
{
WeakRefCounter *newWeakRef = nullptr;
if (other != nullptr) {
newWeakRef = other->CreateWeakRef(other);
if (newWeakRef != nullptr) {
newWeakRef->IncWeakRefCount(this);
}
}
if (refs_ != nullptr) {
refs_->DecWeakRefCount(this);
}
refs_ = newWeakRef;
return *this;
}
template <typename T>
template <typename O>
wptr<T> &wptr<T>::operator=(O *other)
{
T *object = reinterpret_cast<T *>(other);
WeakRefCounter *newWeakRef = nullptr;
if (object != nullptr) {
newWeakRef = object->CreateWeakRef(object);
if (newWeakRef != nullptr) {
newWeakRef->IncWeakRefCount(this);
}
}
if (refs_ != nullptr) {
refs_->DecWeakRefCount(this);
}
refs_ = newWeakRef;
return *this;
}
template <typename T>
inline wptr<T> &wptr<T>::operator=(const wptr<T> &other)
{
if (other.refs_ != nullptr) {
other.refs_->IncWeakRefCount(this);
}
if (refs_ != nullptr) {
refs_->DecWeakRefCount(this);
}
refs_ = other.refs_;
return *this;
}
template <typename T>
inline wptr<T> &wptr<T>::operator=(const sptr<T> &other)
{
WeakRefCounter *newWeakRef = nullptr;
if (other.GetRefPtr() != nullptr) {
newWeakRef = other->CreateWeakRef(other.GetRefPtr());
if (newWeakRef != nullptr) {
newWeakRef->IncWeakRefCount(this);
}
}
if (refs_ != nullptr) {
refs_->DecWeakRefCount(this);
}
refs_ = newWeakRef;
return *this;
}
template <typename T>
template <typename O>
wptr<T> &wptr<T>::operator=(const wptr<O> &other)
{
if (other.refs_ != nullptr) {
other.refs_->IncWeakRefCount(this);
}
if (refs_ != nullptr) {
refs_->DecWeakRefCount(this);
}
refs_ = other.refs_;
return *this;
}
template <typename T>
template <typename O>
wptr<T> &wptr<T>::operator=(const sptr<O> &other)
{
WeakRefCounter *newWeakRef = nullptr;
if (other.GetRefPtr() != nullptr) {
newWeakRef = other->CreateWeakRef(other.GetRefPtr());
if (newWeakRef != nullptr) {
newWeakRef->IncWeakRefCount(this);
}
}
if (refs_ != nullptr) {
refs_->DecWeakRefCount(this);
}
refs_ = newWeakRef;
return *this;
}
template <typename T>
inline bool wptr<T>::operator==(const T *other) const
{
return GetRefPtr() == other;
}
template <typename T>
inline bool wptr<T>::operator==(const wptr<T> &other) const
{
return GetRefPtr() == other.GetRefPtr();
}
template <typename T>
inline bool wptr<T>::operator==(const sptr<T> &other) const
{
return GetRefPtr() == other.GetRefPtr();
}
template <typename T>
inline const sptr<T> wptr<T>::promote() const
{
return sptr<T>(refs_, true);
}
template <typename T>
inline wptr<T>::~wptr()
{
if (refs_ != nullptr) {
refs_->DecWeakRefCount(this);
}
}
}
#endif