15 Star 64 Fork 182

OpenHarmony/commonlibrary_c_utils

Create your Gitee Account
Explore and code with more than 13.5 million developers,Free private repositories !:)
Sign up
文件
Clone or Download
refbase.h 42.73 KB
Copy Edit Raw Blame History
yp9522 authored 2025-01-20 09:39 +08:00 . 增加log打印DomainID
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
/*
* Copyright (c) 2021 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 SmartPointer is a pointer-like class.
*
* This class simulates a pointer while providing
* enhanced features, such as automatic memory management.\n
* Automatic memory management helps to deallocate
* memory resources correctly when an object's life time expires.
*/
#ifndef UTILS_BASE_REFBASE_H
#define UTILS_BASE_REFBASE_H
#include <atomic>
#include <functional>
#ifdef DEBUG_REFBASE
#include <mutex>
#endif
namespace OHOS {
/**
* @ingroup SmartPointer
* @brief A value indicates no strong references ever.
*/
#define INITIAL_PRIMARY_VALUE (1 << 28)
class RefBase;
#if ((defined DEBUG_REFBASE) && (!defined PRINT_TRACK_AT_ONCE))
class RefTracker;
#endif
/**
* @ingroup SmartPointer
* @brief Reference counter class. Such a class records two kinds
* of references to the corresponding RefBase object and one kind
* of references to the RefCounter object itself.
*
* There are two different references for a single object.\n
* A strong reference holds the reference directly pointing to the object,
* and the object should be alive as long as the strong reference exists.\n
* A weak reference holds a reference indirectly pointing to the object,
* and the object is not always alive/existent
* even if the weak reference exists.
* @note The preceding descriptions are valid only when smart pointers
* are properly used.
*/
class RefCounter {
public:
/**
* @brief Callback function used 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 Sets the callback function.
*
* @param callback Callback function used to delete
* the corresponding RefBase object.
*/
void SetCallback(const RefPtrCallback& callback);
/**
* @brief Removes the current callback function by setting it to a `nullptr`.
*/
void RemoveCallback();
/**
* @brief Gets the count of references to the RefCounter object.
*
* @return Count of references to the RefCounter object.
*/
int GetRefCount();
/**
* @brief Increments the count of references to the RefCounter object by 1.
*/
void IncRefCount();
/**
* @brief Decrements the count of references to the RefCounter object by 1.
*
* Once the count reaches 0 after being decremented,
* `delete this` will be called to deallocate this RefCounter object.
*/
void DecRefCount();
/**
* @brief Checks if the pointer to the callback function is a `nullptr`.
*
* @return `true` if the callback function is a `nullptr`;
* `false` otherwise.
*/
bool IsRefPtrValid();
/**
* @brief Increments the count of strong references to the
* corresponding RefBase object by 1.
*
* @return Original count before increment.
*/
int IncStrongRefCount(const void *objectId);
/**
* @brief Decrements the count of strong references to the
* corresponding RefBase object by 1.
*
* @return Original count before decrement.
* @note If the strong reference never exists,
* decrement will be ineffective.
*/
int DecStrongRefCount(const void *objectId);
/**
* @brief Gets the count of strong references to the
* corresponding RefBase object.
*
* @return Count of strong references.
*/
int GetStrongRefCount();
/**
* @brief Increments the count weak references to the
* corresponding RefBase object by 1.
*
* @return Original count before increment.
*/
int IncWeakRefCount(const void *objectId);
/**
* @brief Decrements the count of weak references to the
* corresponding RefBase object by 1.
*
* @return Original (before decrement) value of atomicWeak_.
* @note If the count reaches 0 after being decremented, the
* corresponding RefBase object with no strong reference ever,
* or the RefBase object with 0 strong reference but an extended
* 'life time', will be deallocated.
*/
int DecWeakRefCount(const void *objectId);
/**
* @brief Gets the count of weak references to the
* corresponding RefBase object.
*
* @return Count of weak references.
*/
int GetWeakRefCount();
/**
* @brief Sets the number of attempts to increment.
*/
void SetAttemptAcquire();
/**
* @brief Get the current times of attempts,this interface is only for IPC use.
*/
int GetAttemptAcquire();
/**
* @brief Check if the number of attempts is greater than 0.
*
* @return `true` if the number of attempts is greater than 0;
* `false` otherwise.
*/
bool IsAttemptAcquireSet();
/**
* @brief Clears number of attempts to increment.
*/
void ClearAttemptAcquire();
/**
* @brief Attempts to increment the count of strong references 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 `true` if the attempt is successful; `false` otherwise.
*/
bool AttemptIncStrongRef(const void *objectId, int &outCount);
// Only for IPC use.
/**
* @brief Attempts to increment the count of strong references to the
* the corresponding RefBase object by 1 (simplified).
*
* @return `true` if the attempt is successful; `false` otherwise.
* @note Only for IPC use.
*/
bool AttemptIncStrong(const void *objectId);
/**
* @brief Checks if the corresponding RefBase object
* has an extended life-time.
*
* @return `true` if success; `false` otherwise.
*/
bool IsLifeTimeExtended();
/**
* @brief Extends the life-time of corresponding RefBase object.
*
* This allows the corresponding object keep alive
* even if there is no strong reference.
* @note The RefBase object will be deallocated
* if the count of weak references also reaches 0.
*/
void ExtendObjectLifetime();
#ifdef OHOS_PLATFORM
using CanPromote = std::function<bool()>;
void SetCanPromote(const CanPromote& canPromote);
void RemoveCanPromote();
bool IsCanPromoteValid();
#endif
#if ((defined DEBUG_REFBASE) && (!defined TRACK_ALL))
/**
* @brief Enables tracking. It is applicable to debugging only.
*/
void EnableTracker();
#endif
#if ((defined DEBUG_REFBASE) && (defined PRINT_TRACK_AT_ONCE))
/**
* @brief Enables tracking with domainId. It is applicable to debugging only.
*/
void EnableTrackerWithDomainId(unsigned int domainId);
#endif
private:
void DebugRefBase(const void *objectId);
void RefBaseDebugPrint(int curCount, const void* caller, const void* objectId,
const char* operation, const char* countType);
std::atomic<int> atomicStrong_; // = (num of sptr) or Initial-value
std::atomic<int> atomicWeak_; // = (num of sptr)+(num of WeakRefCounter)
std::atomic<int> atomicRefCount_; // = (num of WeakRefCounter) + 1
std::atomic<unsigned int> atomicFlags_; // Life-time extended flag
std::atomic<int> atomicAttempt_; // Number of attempts
RefPtrCallback callback_ = nullptr; // Callback function to deallocate the corresponding RefBase object
static constexpr unsigned int FLAG_EXTEND_LIFE_TIME = 0x00000002; // Extended life-time bit to be set via logic-OR
#ifdef OHOS_PLATFORM
CanPromote canPromote_ = nullptr;
#endif
#ifdef DEBUG_REFBASE
#ifdef TRACK_ALL
bool enableTrack = true;
#else
bool enableTrack = false;
#endif
std::mutex trackerMutex; // To ensure refTracker be thread-safe
#ifdef PRINT_TRACK_AT_ONCE
unsigned int domainId_ = 0xD003D00;
#else
RefTracker* refTracker = nullptr;
void GetNewTrace(const void* objectId);
void PrintTracker();
#endif
#endif
};
/**
* @ingroup SmartPointer
* @brief An intermediate class to represent the weak reference
* to the correspond RefBase object.
*
* A WeakRefCounter object can be shared by multiple wptr objects.\n
* It holds the references to the corresponding RefBase and RefCounter object.
* Those two references will be set as `nullptr` when the weak referenced
* target and its RefCounter object are deallocated. The WeakRefCounter
* object can remain alive even if the referenced target is deallocated.
*/
class WeakRefCounter {
public:
/**
* @brief Constructs a WeakRefCounter object.
*
* @param counter Pointer to corresponding RefCounter object.
* @param cookie Pointer to corresponding RefBase object.
*/
WeakRefCounter(RefCounter *counter, void *cookie);
virtual ~WeakRefCounter();
/**
* @brief Gets the current pointer to the corresponding RefBase object.
*
* @return A void pointer to the RefBase object.
* If the corresponding object is not alive, a `nullptr` will be returned.
* @note A void pointer means that you should cast it to the real type,
* since it can be any subclass of RefBase.
*/
void *GetRefPtr();
/**
* @brief Increments the count of references to this WeakRefCounter object.
*
* @note This count is different from the count of weak references
* in RefCounter. It is equal to the count of wptrs directly
* referenced to this WeakRefCount object.
* @see RefCounter
*/
void IncWeakRefCount(const void *objectId);
/**
* @brief Decrements the count of references to this WeakRefCounter object.
*
* @note This WeakRefCounter object will be deallocated when this count
* reaches 0.
*/
void DecWeakRefCount(const void *objectId);
/**
* @brief Gets the count recorded by this WeakRefCounter object.
*
* @return Count recorded by this WeakRefCounter object.
* @note The count is different from that in RefCounter.
* @see RefCounter::GetWeakRefCount()
*/
int GetWeakRefCount() const;
/**
* @brief Attempts to increment the count of strong references to
* the corresponding RefBase object (to promote a wptr to a sptr).
*
* @return `true` after a success increment.
*/
bool AttemptIncStrongRef(const void *objectId);
private:
std::atomic<int> atomicWeak_; // Count of references to this
// WeakRefCounter object
// The value is equal to the count of wptrs
// that references this WeakRefCounter object.
RefCounter *refCounter_ = nullptr; // Reference to the RefCounter object of
// the corresponding RefBase object
void *cookie_ = nullptr; // Pointer to the corresponding RefBase object
};
/**
* @ingroup SmartPointer
* @brief A base class of subclasses that can be managed by SmartPointer.
*
* @note All classes which intend to be managed by SmartPointer should be
* derived from RefBase.
*/
class RefBase {
public:
RefBase();
/**
* @brief Copy constructor of RefBase.
*
* @note This function constructs a new RefCounter object
* and binds it to the RefBase object.
*/
RefBase(const RefBase &);
/**
* @brief Copy assignment operator of RefBase.
*
* @note This function unbinds this RefBase object from the
* original RefCounter object, and then binds it to the
* 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 function binds this RefBase object with the RefCounter
* object of the argument `other`, which will unbind the
* RefCounter object. No counts operation will be processed.
*/
RefBase &operator=(RefBase &&other) noexcept;
virtual ~RefBase();
/**
* @brief Callback function to deallocate this object.
*
* This function provides the default implementation to deallocate
* this RefBase object by simply calling `delete(this)`.
*/
virtual void RefPtrCallback();
/**
* @brief Extends the life time of the RefBase object.
*
* @note The object whose life time has been extended will not be
* deallocated if the count of weak references, instead of strong
* references, reaches 0.
*/
void ExtendObjectLifetime();
/**
* @brief Increments the count of strong references.
*
* `OnFirstStrongRef()`, which is an empty function by default,
* will be called when the first strong reference is established.
*
* @note This function automatically increments the count of weak
* references meanwhile.
*/
void IncStrongRef(const void *objectId);
/**
* @brief Decrements the count of strong references.
*
* If the life time is not extended, this object will be deallocated
* when the count of strong references reaches 0.\n
* `OnLastStrongRef()`, which is an empty function by default,
* will be called when the last strong reference is deleted.
*/
void DecStrongRef(const void *objectId);
/**
* @brief Gets the count of strong references.
*
* @return Count of strong references. The value is 0 if the
* corresponding RefCounter object does not exist.
* @note This function is valid only when corresponding RefCounter
* object exists.
*/
int GetSptrRefCount();
/**
* @brief Creates a weak reference to this RefBase object.
*
* @param cookie Void pointer to this RefBase object.
* @return Pointer to the newly created WeakRefCounter object.
* @note Use this function with related functions of wptr.
* Do not use it independently.
*/
WeakRefCounter *CreateWeakRef(void *cookie);
/**
* @brief Gets the pointer to corresponding counter object.
*
* @return Pointer to the counter object.
*/
RefCounter *GetRefCounter() const;
/**
* @brief Increments the count of weak references.
*
* @note This function is valid only when corresponding RefCounter
* object exists.
*/
void IncWeakRef(const void *objectId);
/**
* @brief Decrements the count of weak references.
*
* @note This function is valid only when corresponding RefCounter
* object exists.
*/
void DecWeakRef(const void *objectId);
/**
* @brief Gets the count of weak references.
*
* @return Count of weak references. The value is 0 if the corresponding
* RefCounter object does not exist.
*/
int GetWptrRefCount();
/**
* @brief Attempts to increment the count of strong references.
*
* `OnFirstStrongRef()`, which is an empty function by default, will be
* called when the first strong reference is established.
*
* @return `true` if the increment is successful; `false` otherwise.
* @note The count of attempts will increment by 1
* after a successful increment.
*/
bool AttemptAcquire(const void *objectId);
/**
* @brief Check attempt acquire is setted,this interface is only for IPC use.
* This interface must come after the RefBase::AttemptIncStrong or RefBase::AttemptAcquire function,
* And ensuring thread safety in multi-threaded scenarios.
*
* @note This fuction is extracted from `IncStrongRef()`
* It is only for IPC use.
*/
void CheckIsAttemptAcquireSet(const void *objectId);
/**
* @brief Attempts to increment the count of strong references.
*
* `OnFirstStrongRef()`, which is an empty function by default, will be
* called when the first strong reference is established.
* @return `true` if the increment is successful; `false` otherwise.
* @note Use this function in the copy constructor of sptr in scenario of
* interaction between sptr and wptr. Avoid using it independently.
*/
bool AttemptIncStrongRef(const void *objectId);
// Only for IPC use.
/**
* @brief Attempts to increment the count of strong references.
*
* @return `true` if the increment is successful; `false` otherwise.
* @note If the operation is successful, the count of successful attempts
* will increment by 1.
* @note This function is a simplified version of `AttemptAcquire`.
* It is only for IPC use.
*/
bool AttemptIncStrong(const void *objectId);
/**
* @brief Checks if the count of successful attempts is greater than 0.
*
* @return `true` if the count of successful attempts is greater than 0;
* `false` if the count of successful attempts is not greater than 0
* or the corresponding RefCounter object does not exist.
*/
bool IsAttemptAcquireSet();
/**
* @brief Checks if the life time of this RefBase object has been extended.
*
* @return `true` if the life time of this RefBase object has been extended;
* `false` if the RefBase object has a normal life time or the corresponding
* RefCounter object does not exist.
*/
bool IsExtendLifeTimeSet();
/**
* @brief Called when the first strong reference is established.
*
* @note It is an empty function by default.
*/
virtual void OnFirstStrongRef(const void *);
/**
* @brief Called when the last strong reference is deleted.
*
* @note It is an empty function by default.
*/
virtual void OnLastStrongRef(const void *);
/**
* @brief Called when the last weak reference is deleted.
*
* @note It is an empty function by default.
*/
virtual void OnLastWeakRef(const void *);
/**
* @brief Called when `wptr::Promote()` is invoked.
*
* @return `true` if success; `false` otherwise.
*/
virtual bool OnAttemptPromoted(const void *);
/**
* @brief Enables tracking of the RefBase object. This function will
* be implemented only if DEBUG_REFBASE, but not TRACK_ALL, is defined.
*/
void EnableTracker();
/**
* @brief Enables tracking of the RefBase object with domainId. This function will
* be implemented only if DEBUG_REFBASE, but not TRACK_ALL, is defined.
*/
void EnableTrackerWithDomainId(unsigned int domainId);
#ifdef OHOS_PLATFORM
virtual bool CanPromote();
#endif
private:
RefCounter *refs_ = nullptr; // Pointer to the corresponding reference
// counter of this RefBase object
};
template <typename T>
class wptr;
/**
* @ingroup SmartPointer
* @brief Strong reference smart pointer to a RefBase object
* (or an object of its subclass).
*
* 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 Create a new object with class type (T) and provide a new sptr to manage it.
*
* @note We strongly recommend using `sptr::MakeSptr` to create a object and manage it.
* This approach avoids object pointer leaks, which can avoid many potential memory problems.
*
* @return A sptr which manage a new object with class type (T).
* @param args Constructor parameters of the new object to be managed by sptr.
*/
template <typename... Args>
static inline sptr<T> MakeSptr(Args&&... args);
/**
* @brief Constructor with the specified object to be managed.
* And We do not recommend using this interface to create an sptr object.
* Using the interface `sptr::MakeSptr` is better
*
* @note A null sptr will be created if `other` is `nullptr`.
* @param other Object to be managed by sptr.
*/
sptr(T *other);
/**
* @brief Copy constructor for sptr with the 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 The original strong reference in target sptr object will
* be removed.
*/
sptr<T> &operator=(sptr<T> &&other);
/**
* @brief Copy Constructor for sptr with the 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 used to promote the process of wptr.
*
* @param p WeakRefCounter object which hold the reference to the
* managed object.
* @param force Used to distinguish from other constructors.
*/
inline sptr(WeakRefCounter *p, bool force);
/**
* @brief Gets the pointer to the managed object.
*
* @return Pointer of the specific managed class type.
*/
inline T *GetRefPtr() const
{
return refs_;
}
/**
* @brief Sets the pointer to the managed object.
*
* @param other Another pointer object to be managed by sptr.
* @note Avoid using this function independently. Otherwise,
* a mismatch of the reference count will arise, leading to memory problems.
*/
inline void ForceSetRefPtr(T *other);
/**
* @brief Removes the reference to the managed object held by current sptr.
*
* @note This function will make this sptr a "null sptr".
*/
void clear();
/**
* @brief Type conversion operator.
*
* @return Raw pointer to the managed object.
* @note The sptr object will not be converted. Only the member raw
* pointer will be returned.
*/
inline operator T *() const
{
return refs_;
}
/**
* @brief Explicit boolean conversion operator.
*
* @return `true` if refbase object is not a "null ptr"; `false` otherwise.
*/
inline explicit operator bool() const
{
return refs_ != nullptr;
}
/**
* @brief Dereference operator.
*
* This function will return the object managed by this sptr.
*
* @return Reference to the specific object managed by sptr.
*/
inline T &operator*() const
{
return *refs_;
}
/**
* @brief Member selection operator.
*
* This function will return the specified member of the object
* managed by this sptr.
*/
inline T *operator->() const
{
return refs_;
}
/**
* @brief Copy assignment operator with the specified object to be managed.
* And We do not recommend using this interface to create an sptr object.
* Using the interface `sptr::MakeSptr` is better.
*
* @note The original reference will be removed, and a 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
* the same managed class type (T).
*
* @note The original reference will be removed, and the same object
* with the input sptr object will be managed by this sptr.
* @param other Another sptr object with the same managed class type (T).
*/
sptr<T> &operator=(const sptr<T> &other);
/**
* @brief Copy assignment operator for wptr with
* the same managed class type (T).
*
* @note The original reference will be removed, and the same object
* with the input wptr object will be managed by this sptr.
* @note If the operation fails, this sptr will turn to be a "null sptr".
* @param other Another wptr object with the same managed class type (T).
*/
sptr<T> &operator=(const wptr<T> &other);
/**
* @brief Copy assignment operator for sptr with
* a different managed class type (O).
*
* @note The original reference will be removed, and the same object
* with the input sptr object will be managed by this sptr.
* @note This sptr will interpret the managed object as the type (T).
* @param other Another sptr object with a different managed class type (O).
*/
template <typename O>
sptr<T> &operator=(const sptr<O> &other);
/**
* @brief Equal-to operator between the sptr and raw pointer.
*
* @param other Input raw pointer.
* @return `true` if the sptr points to the same object with input
* raw pointer; `false` otherwise.
*/
bool operator==(const T *other) const;
/**
* @brief Not-equal-to operator between the sptr and raw pointer.
*
* @param other Input raw pointer.
* @return `true` if the sptr does not point to the same object
* with input raw pointer; `false` otherwise.
*/
inline bool operator!=(const T *other) const
{
return !operator==(other);
}
/**
* @brief Equal-to operator between the sptr and wptr.
*
* @param other Input wptr.
* @return `true` if the same object is managed by the sptr and wptr;
* `false` otherwise.
*/
bool operator==(const wptr<T> &other) const;
/**
* @brief Not-equal-to operator between the sptr and wptr.
*
* @param other Input wptr.
* @return `true` if different objects are managed by the sptr and wptr;
* `false` otherwise.
*/
inline bool operator!=(const wptr<T> &other) const
{
return !operator==(other);
}
/**
* @brief Equal-to operator between two sptrs.
*
* @param other Input sptr.
* @return `true` if the same object is managed by two sptrs;
* `false` otherwise.
*/
bool operator==(const sptr<T> &other) const;
/**
* @brief Not-equal-to operator between sptrs.
*
* @param other Input sptr.
* @return `true` if different objects are managed by two sptrs;
* `false` otherwise.
*/
inline bool operator!=(const sptr<T> &other) const
{
return !operator==(other);
}
private:
T *refs_ = nullptr; // Raw pointer to the specific managed object
};
template <typename T>
template <typename... Args>
sptr<T> sptr<T>::MakeSptr(Args&&... args)
{
T *ptr = new T(std::forward<Args>(args)...);
sptr<T> res;
res.ForceSetRefPtr(ptr);
ptr->IncStrongRef(ptr);
return res;
}
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 /* force */)
{
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 object
* (or an object of its subclass).
*
* A weak reference indirectly references the RefBase object
* and directly references 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 the specified object to be managed.
*
* This function will create WeakRefCounter object for `other`
* and set the count of weak references to 1.
*
* @note A 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 the same managed class type (T).
*
* This function will share the WeakRefCounter object of `other` with this
* wptr and set the count of weak references properly.
*
* @param other Another wptr with the same managed class type (T).
*/
wptr(const wptr<T> &other);
/**
* @brief Copy constructor for sptr with the same managed class type (T).
*
* This function will create a WeakRefCounter object for the managed
* object of `other`, and set the count of weak references properly.
*
* @param other Another sptr with the same managed class type (T).
* @tparam T Specific class type managed by `other`.
*/
wptr(const sptr<T> &other);
/**
* @brief Copy constructor for wptr with a different managed class type (O).
*
* This function is the same as wptr<T>::wptr(const wptr<T> &other).
*
* @tparam O Class type managed by `other`.
* @param other Another wptr with a 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 a different managed class type (O).
*
* This function is the same as wptr<T>::wptr(const sptr<T> &other).
*
* @param other Another sptr with the 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 the specified object to be managed.
*
* @note The current wptr will unbind the original WeakRefCounter object,
* create a new WeakRefCounter object, and then set the count of weak
* references properly.
* @param other Another object to be managed by this wptr.
*/
wptr<T> &operator=(T *other);
/**
* @brief Copy assignment operator with the 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 processed.
* @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 the same managed class
* type (T).
*
* @note The current wptr will unbind the original WeakRefCounter object,
* share the WeakRefCounter object with `other`, and then set the count of
* weak references properly.
* @param other Another wptr object. Objects managed by it will also be
* managed by this wptr.
*/
wptr<T> &operator=(const wptr<T> &other);
/**
* @brief Copy assignment operator for sptr with the same managed class
* type (T).
*
* @note The current wptr will unbind the original WeakRefCounter object,
* create a new WeakRefCounter object, and then set the count of weak
* references properly.
* @param other A sptr object. Objects managed by it will also be
* managed by this wptr.
*/
wptr<T> &operator=(const sptr<T> &other);
/**
* @brief Copy assignment operator for wptr with a different managed class
* type (O).
*
* @note This function is the same as wptr<T> &operator=(const wptr<T> &).
* Note that no cast here is processed.
* @param other An wptr object. Objects 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 a different managed class
* type (O).
*
* @note This function is the same as
* wptr<T> &wptr<T>::operator=(const sptr<T> &).
* Note that no cast here is processed.
* @param other An sptr object. Objects 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.
*
* This function will return the object managed by this wptr.
*
* @return Specific object managed by wptr.
*/
inline T &operator*() const
{
return *GetRefPtr();
}
/**
* @brief Member selection operator.
*
* This function will return the specified object member managed
* by this wptr.
*/
inline T *operator->() const
{
return reinterpret_cast<T *>(refs_->GetRefPtr());
}
/**
* @brief Equal-to operator between the wptr and raw pointer.
*
* @param other Input raw pointer.
* @return `true` if two pointers have the same value; `false` otherwise.
*/
bool operator==(const T *other) const;
/**
* @brief Not-equal-to operator between the wptr and raw pointer.
*
* @param other Input raw pointer.
* @return `true` if two pointers have different values; `false` otherwise.
*/
inline bool operator!=(const T *other) const
{
return !operator==(other);
};
/**
* @brief Equal-to operator between two wptrs.
*
* @param other Input reference to a wptr object.
* @return `true` if two pointers have the same value; `false` otherwise.
*/
bool operator==(const wptr<T> &other) const;
/**
* @brief Not-equal-to operator between two wptrs.
*
* @param other Input reference to a wptr object.
* @return `true` if two pointers have different values; `false` otherwise.
*/
inline bool operator!=(const wptr<T> &other) const
{
return !operator==(other);
}
/**
* @brief Equal-to operator between the wptr and input sptr object.
*
* @param other Input reference to an sptr object.
* @return true` if two pointers have the same value; `false` otherwise.
*/
bool operator==(const sptr<T> &other) const;
/**
* @brief Not-equal-to operator between the wptr and input sptr object.
*
* @param other Input reference to an sptr object.
* @return `true` if two pointers have different values; `false` otherwise.
*/
inline bool operator!=(const sptr<T> &other) const
{
return !operator==(other);
}
/**
* @brief Gets the pointer to the RefBase object.
*
* @return Raw pointer to the RefBase object.
* @note `nullptr` will be returned if the managed object has been
* deallocated.
*/
T *GetRefPtr() const;
/**
* @brief Gets the count of weak references in a WeakRefCounter object.
*
* The value indicates how many wptrs share the same WeakRefCounter object.
*
* @return Count of weak references.
* @note Only for test.
*/
inline int GetWeakRefCount() const
{
return refs_->GetWeakRefCount();
}
/**
* @brief Attempts to increment the count of strong references in
* the managed object.
*
* @return `true` if the increment is successful; `false` otherwise.
* @note Avoid using this function independently. Use `promote()` instead.
*/
inline bool AttemptIncStrongRef(const void *objectId) const
{
return refs_->AttemptIncStrongRef(objectId);
}
/**
* @brief Promotes a wptr to an sptr.
*
* This function will create an sptr object based on the object
* managed by this wptr.
*
* @note The original weak reference will be retained.
* If the promotion fails, a "null sptr" will be returned.
*/
const sptr<T> promote() const;
~wptr();
private:
WeakRefCounter *refs_ = nullptr; // Pointer to the corresponding WeakRefCounter object
};
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);
}
}
} // namespace OHOS
#endif
/**@}*/
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openharmony/commonlibrary_c_utils.git
git@gitee.com:openharmony/commonlibrary_c_utils.git
openharmony
commonlibrary_c_utils
commonlibrary_c_utils
master

Search