[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/ClearFoundry/ClearScript/master/ClearScriptV8/SharedPtr.h [Back]  [Original]

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

#pragma once

//-----------------------------------------------------------------------------
// SharedPtrTarget
//-----------------------------------------------------------------------------

class SharedPtrTarget
{
    PROHIBIT_COPY(SharedPtrTarget)

public:

    RefCount* GetRefCount()
    {
        return &m_RefCount;
    }

protected:

    class AddRefScope final
    {
        PROHIBIT_COPY(AddRefScope)
        PROHIBIT_HEAP(AddRefScope)

    public:

        explicit AddRefScope(RefCount* pRefCount):
            m_pRefCount(pRefCount),
            m_RefCountValue(pRefCount->Increment())
        {
        }

        size_t GetRefCountValue() const
        {
            return m_RefCountValue;
        }

        ~AddRefScope()
        {
            m_pRefCount->Decrement();
        }

    private:

        RefCount* m_pRefCount;
        size_t m_RefCountValue;
    };

    SharedPtrTarget():
         m_RefCount(0)
    {
    }

private:

    RefCount m_RefCount;
};

//-----------------------------------------------------------------------------

#define BEGIN_ADDREF_SCOPE \
    { \
        DISABLE_WARNING(4456) /* declaration hides previous local declaration */ \
        AddRefScope t_AddRefScope(GetRefCount()); \
        DEFAULT_WARNING(4456)

#define END_ADDREF_SCOPE \
        IGNORE_UNUSED(t_AddRefScope); \
    }

//-----------------------------------------------------------------------------
// SharedPtrTraits
//-----------------------------------------------------------------------------

template 
struct SharedPtrTraits final: StaticBase
{
    static void Destroy(T* pTarget)
    {
        delete pTarget;
    }
};

//-----------------------------------------------------------------------------
// SharedPtr
//-----------------------------------------------------------------------------

template 
class SharedPtr final
{
    template 
    friend class SharedPtr;

public:

    SharedPtr()
    {
        Initialize();
    }

    explicit SharedPtr(std::nullptr_t)
    {
        Initialize();
    }

    explicit SharedPtr(T* pTarget)
    {
        Initialize(pTarget);
    }

    SharedPtr(const SharedPtr& that)
    {
        CopyInitialize(that);
    }

    SharedPtr(SharedPtr&& that) noexcept
    {
        MoveInitialize(that);
    }

    template 
    explicit SharedPtr(const SharedPtr& that)
    {
        CopyInitialize(that);
    }

    template 
    explicit SharedPtr(SharedPtr&& that)
    {
        MoveInitialize(that);
    }

    const SharedPtr& operator=(std::nullptr_t)
    {
        Empty();
        return *this;
    }

    const SharedPtr& operator=(T* pTarget)
    {
        SharedPtr spHolder(m_pTarget, m_pRefCount);
        Initialize(pTarget);
        return *this;
    }

    const SharedPtr& operator=(const SharedPtr& that)
    {
        Copy(that);
        return *this;
    }

    const SharedPtr& operator=(SharedPtr&& that) noexcept
    {
        Move(that);
        return *this;
    }

    template 
    const SharedPtr& operator=(const SharedPtr& that)
    {
        Copy(that);
        return *this;
    }

    template 
    const SharedPtr& operator=(SharedPtr&& that)
    {
        Move(that);
        return *this;
    }

    T* operator->() const
    {
        _ASSERTE(m_pTarget != nullptr);
        return m_pTarget;
    }

    T& operator*() const
    {
        _ASSERTE(m_pTarget != nullptr);
        return *m_pTarget;
    }

    template 
    TOther& DerefAs() const
    {
        _ASSERTE(m_pTarget != nullptr);
        return *static_cast(m_pTarget);
    }

    bool operator==(std::nullptr_t) const
    {
        return IsEmpty();
    }

    bool operator==(T* pThat) const
    {
        return m_pTarget == pThat;
    }

    template 
    bool operator==(const SharedPtr& that) const
    {
        return m_pTarget == that.m_pTarget;
    }

    bool operator!=(std::nullptr_t) const
    {
        return !operator==(nullptr);
    }

    bool operator!=(T* pThat) const
    {
        return !operator==(pThat);
    }

    template 
    bool operator!=(const SharedPtr& that) const
    {
        return !operator==(that);
    }

    template 
    SharedPtr CastTo() const
    {
        AddRef();
        return SharedPtr(static_cast(m_pTarget), m_pRefCount);
    }

    bool IsEmpty() const
    {
        return m_pTarget == nullptr;
    }

    void Empty()
    {
        SharedPtr spHolder(std::move(*this));
    }

    ~SharedPtr()
    {
        Release();
    }

private:

    SharedPtr(T* pTarget, RefCount* pRefCount)
    {
        Initialize(pTarget, pRefCount);
    }

    void Initialize()
    {
        m_pTarget = nullptr;
        m_pRefCount = nullptr;
    }

    void Initialize(T* pTarget)
    {
        m_pTarget = pTarget;
        m_pRefCount = (m_pTarget != nullptr) ? AttachRefCount(m_pTarget) : nullptr;
    }

    void Initialize(T* pTarget, RefCount* pRefCount)
    {
        m_pTarget = pTarget;
        m_pRefCount = pRefCount;
    }

    template 
    void CopyInitialize(const SharedPtr& that)
    {
        Initialize(that.m_pTarget, that.m_pRefCount);
        AddRef();
    }

    template 
    void MoveInitialize(SharedPtr& that)
    {
        Initialize(that.m_pTarget, that.m_pRefCount);
        that.Initialize();
    }

    template 
    void Copy(const SharedPtr& that)
    {
        SharedPtr spHolder(m_pTarget, m_pRefCount);
        CopyInitialize(that);
    }

    template 
    void Move(SharedPtr& that)
    {
        SharedPtr spHolder(m_pTarget, m_pRefCount);
        MoveInitialize(that);
    }

    void AddRef() const
    {
        if (m_pTarget != nullptr)
        {
            _ASSERTE(m_pRefCount);
            m_pRefCount->Increment();
        }
    }

    void Release()
    {
        if (m_pTarget != nullptr)
        {
            T* pTarget = m_pTarget;
            m_pTarget = nullptr;

            RefCount* pRefCount = m_pRefCount;
            m_pRefCount = nullptr;

            _ASSERTE(pRefCount);
            if (pRefCount->Decrement() == 0)
            {
                DetachRefCount(pTarget, pRefCount);
                SharedPtrTraits::Destroy(pTarget);
            }
        }
    }

    static RefCount* AttachRefCount(SharedPtrTarget* pTarget)
    {
        RefCount* pRefCount = pTarget->GetRefCount();
        pRefCount->Increment();
        return pRefCount;
    }

    static void DetachRefCount(SharedPtrTarget* /*pTarget*/, RefCount* /*pRefCount*/)
    {
    }

    static RefCount* AttachRefCount(void* /*pvTarget*/)
    {
        return new RefCount(1);
    }

    static void DetachRefCount(void* /*pvTarget*/, RefCount* pRefCount)
    {
        delete pRefCount;
    }

    T* m_pTarget;
    RefCount* m_pRefCount;
};

Web Proxy Viewer  |  New URL  |  Original Page