alive_ptr 用于独立的判断原始指针是否有效(存活)的智能指针

#ifndef ALIVE_PTR_H_INCLUDED
#define ALIVE_PTR_H_INCLUDED
#include <atomic>

namespace alive
{
    template<typename T>
    struct alive_ref
    {
        inline ~alive_ref() {}

        inline T* data() { return ptr_.load(); }

        bool ref(int* old_ref = nullptr)
        {
            bool exchanged = false;
            auto old = ref_.load();
            while (old > 0 && !(exchanged = ref_.compare_exchange_weak(old, old + 1)));

            if (exchanged && old_ref)
            {
                *old_ref = old;
            }

            return exchanged;
        }

        bool deref(int* old_ref = nullptr)
        {
            bool exchanged = false;
            auto old = ref_.load();
            while (old > 0 && !(exchanged = ref_.compare_exchange_weak(old, old - 1)));

            if (exchanged && old_ref)
            {
                *old_ref = old;
            }

            return exchanged;
        }

        std::atomic<T*> ptr_{ nullptr };
        std::atomic<int> ref_{ 0 };
    };

    template<typename T>
    class support_alive_ptr
    {
        typedef alive_ref<T> alive_ref_t;

    public:
        static alive_ref_t* getAndRef(T* ptr)
        {
            return internalGetAndRef(ptr);
        }

        inline ~support_alive_ptr()
        {
            auto ref_ptr = ref_.load();
            if (ref_ptr)
            {
                ref_ptr->ptr_.store(nullptr);

                int old_ref = 0;
                if (ref_ptr->deref(&old_ref) && old_ref == 1)
                {
                    ref_.store(nullptr);

                    delete ref_ptr;
                }
            }
        }

        inline int alive_ref_count() const
        {
            auto ref_ptr = ref_.load();

            return ref_ptr ? ref_ptr->ref_.load() : 0;
        }

    private:
        static alive_ref_t* internalGetAndRef(support_alive_ptr<T>* base)
        {
            alive_ref_t* ref_ptr = base->ref_.load();

            if (ref_ptr)
            {
                ref_ptr->ref();
            }
            else
            {
                ref_ptr = new alive_ref_t;
                ref_ptr->ptr_.store(static_cast<T*>(base));
                ref_ptr->ref_.store(2); // 2: 1 held by support_alive_ptr self, 1 for the first alive_ptr

                alive_ref_t* ref_ptr_held{ nullptr };
                if (!base->ref_.compare_exchange_strong(ref_ptr_held, ref_ptr))
                {
                    delete ref_ptr;

                    ref_ptr = ref_ptr_held;
                    ref_ptr->ref();
                }
            }

            return ref_ptr;
        }

        static alive_ref_t* internalGetAndRef(...)
        {
            static_assert(false, "support_alive_ptr<T> is not base of T");
        }

    private:
        std::atomic<alive_ref_t*> ref_{ nullptr };
    };

    template<typename T>
    class alive_ptr
    {
        typedef alive_ref<T> alive_ref_t;

    public:
        inline alive_ptr() {}
        inline alive_ptr(T* ptr) : ref_(ptr ? support_alive_ptr<T>::getAndRef(ptr) : nullptr) {}
        inline alive_ptr(const alive_ptr& rhs) : ref_(rhs.ref_) { if (ref_) { ref_->ref(); } }
        inline alive_ptr(alive_ptr&& rhs) : ref_(rhs.ref_) { if (ref_) { rhs.ref_ = nullptr; } }
        inline ~alive_ptr() { tryToDerefAndDelete(); }

        inline alive_ptr& operator=(const alive_ptr& rhs)
        {
            internalSet(rhs.ref_);

            return *this;
        }

        inline alive_ptr& operator=(alive_ptr&& rhs)
        {
            if (rhs.ref_ != ref_)
            {
                tryToDerefAndDelete();

                ref_ = rhs.ref_;
                rhs.ref_ = nullptr;
            }

            return *this;
        }

        inline bool isNull() const { return ref_ == nullptr || ref_->data() == nullptr; }
        inline bool isAlive() const { return !isNull(); }
        inline bool operator !() const { return isNull(); }
        inline T *data() const { return ref_ == nullptr ? nullptr : ref_->data(); }
        inline T* operator->() const { return data(); }
        inline T& operator*() const { return *data(); }
        inline operator T*() const { return data(); }
        inline void clear() { *this = alive_ptr(); }

    private:
        inline void internalSet(alive_ref_t* new_ref)
        {
            if (ref_ == new_ref) { return; }

            if (new_ref) { new_ref->ref(); }

            tryToDerefAndDelete();

            ref_ = new_ref;
        }

        inline void tryToDerefAndDelete()
        {
            if (ref_)
            {
                int old_ref = 0;
                if (ref_->deref(&old_ref) && old_ref == 1)
                {
                    delete ref_;
                }
            }
        }

    private:
        alive_ref_t* ref_{ nullptr };
    };
}

#endif

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值