/*
* Copyright (c) 2024 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.
*/
#ifndef META_BASE_SHARED_PTR_INTERNALS_H
#define META_BASE_SHARED_PTR_INTERNALS_H
#include
#include
#include
#include
#include
#include
BASE_BEGIN_NAMESPACE()
namespace Internals {
template
using EnableIfPointerConvertible = BASE_NS::enable_if_t>;
class ControlBlock {
public:
ControlBlock() = default;
virtual ~ControlBlock() = default;
META_NO_COPY_MOVE(ControlBlock)
void AddStrongCopy()
{
CORE_NS::AtomicIncrement(&strongCount_);
}
void AddWeak()
{
CORE_NS::AtomicIncrement(&weakCount_);
}
void Release()
{
if (CORE_NS::AtomicDecrement(&strongCount_) == 0) {
Dispose();
// The strong references are counted as one weak references to keep the control block alive
ReleaseWeak();
}
}
void ReleaseWeak()
{
// The weak count is initialised to 1, so releasing weak pointers does not destroy
// the control block unless there is no more strong references
if (CORE_NS::AtomicDecrement(&weakCount_) == 0) {
Destroy();
}
}
bool AddStrongLock()
{
return CORE_NS::AtomicIncrementIfNotZero(&strongCount_) != 0;
}
int32_t GetStrongCount() const
{
return CORE_NS::AtomicRead(&strongCount_);
}
virtual void Destroy() = 0;
virtual void Dispose() = 0;
private:
// Count of the weak references +1 for the strong references
int32_t weakCount_ { 1 };
int32_t strongCount_ { 1 };
};
class ptr_base {
protected:
ptr_base() = default;
~ptr_base() = default;
ptr_base(const ptr_base&) = default;
ptr_base(ptr_base&&) = default;
ptr_base& operator=(const ptr_base&) = default;
ptr_base& operator=(ptr_base&&) = default;
};
template
class PtrCountedBase : public ptr_base {
public:
// for compatibility
template
bool Compare(const PtrCountedBase& p) const
{
return static_cast(pointer_) == static_cast(p.pointer_);
}
template
bool CompareOwner(const PtrCountedBase& p) const
{
return control_ == p.control_;
}
protected:
PtrCountedBase() = default;
PtrCountedBase(ControlBlock* c) : control_(c) {}
~PtrCountedBase() = default;
PtrCountedBase(const PtrCountedBase&) = default;
PtrCountedBase& operator=(const PtrCountedBase&) = default;
PtrCountedBase(PtrCountedBase&&) = default;
PtrCountedBase& operator=(PtrCountedBase&&) = default;
void InternalReset()
{
control_ = nullptr;
pointer_ = nullptr;
}
protected:
Type* pointer_ {};
ControlBlock* control_ {};
template
friend class PtrCountedBase;
};
template
using DefaultDeleterType = void (*)(T*);
template
class StorageBlock final : public ControlBlock {
public:
explicit StorageBlock(T* ptr) : ptr_ { ptr }
{
}
void Destroy() final
{
delete this;
}
void Dispose() final
{
delete ptr_;
}
private:
T* ptr_ { nullptr };
};
template>
class StorageBlockWithDeleter final : public ControlBlock {
public:
StorageBlockWithDeleter(T* ptr, Deleter deleter) : ptr_ { ptr }, deleter_ { BASE_NS::move(deleter) }
{
}
void Destroy() final
{
delete this;
}
void Dispose() final
{
deleter_(ptr_);
}
private:
T* ptr_ { nullptr };
Deleter deleter_;
};
template
class RefCountedObjectStorageBlock final : public ControlBlock {
public:
using deletableType = BASE_NS::remove_const_t;
explicit RefCountedObjectStorageBlock(T* ptr) : ptr_ { ptr }
{
const_cast(ptr)->Ref();
}
void Destroy() final
{
delete this;
}
void Dispose() final
{
const_cast(ptr_)->Unref();
}
private:
T* ptr_ { nullptr };
};
} // namespace Internals
BASE_END_NAMESPACE()
#endif