/*
 * Copyright 2021 Rive
 */

#ifndef _RIVE_REFCNT_HPP_
#define _RIVE_REFCNT_HPP_

#include <assert.h>

#include <atomic>
#include <cstddef>
#include <type_traits>
#include <utility>

/*
 *  RefCnt : Threadsafe shared pointer baseclass.
 *
 *  The reference count is set to one in the constructor, and goes up on every call to ref(),
 *  and down on every call to unref(). When a call to unref() brings the counter to 0,
 *  delete is called on the object.
 *
 *  rcp : template wrapper for subclasses of RefCnt, to manage assignment and parameter passing
 *  to safely keep track of shared ownership.
 *
 *  Both of these inspired by Skia's SkRefCnt and sk_sp
 */

namespace rive {

class RefCnt {
public:
    RefCnt() : m_refcnt(1) {}

    virtual ~RefCnt() {
        assert(this->debugging_refcnt() == 1);
    }

    void ref() const {
        (void)m_refcnt.fetch_add(+1, std::memory_order_relaxed);
    }

    void unref() const {
        if (1 == m_refcnt.fetch_add(-1, std::memory_order_acq_rel)) {
#ifndef NDEBUG
            // we restore the "1" in debug builds just to make our destructor happy
            (void)m_refcnt.fetch_add(+1, std::memory_order_relaxed);
#endif
            delete this;
        }
    }

    // not reliable in actual threaded scenarios, but useful (perhaps) for debugging
    int32_t debugging_refcnt() const {
        return m_refcnt.load(std::memory_order_relaxed);
    }

private:
    mutable std::atomic<int32_t> m_refcnt;

    RefCnt(RefCnt&&) = delete;
    RefCnt(const RefCnt&) = delete;
    RefCnt& operator=(RefCnt&&) = delete;
    RefCnt& operator=(const RefCnt&) = delete;
};

template <typename T> static inline T* safe_ref(T* obj) {
    if (obj) {
        obj->ref();
    }
    return obj;
}

template <typename T> static inline void safe_unref(T* obj) {
    if (obj) {
        obj->unref();
    }
}

// rcp : smart point template for holding subclasses of RefCnt

template <typename T> class rcp {
public:
    constexpr rcp() : m_ptr(nullptr) {}
    constexpr rcp(std::nullptr_t) : m_ptr(nullptr) {}
    explicit  rcp(T* ptr) : m_ptr(ptr) {}

    rcp(const rcp<T>& other) : m_ptr(safe_ref(other.get())) {}
    rcp(rcp<T>&& other) : m_ptr(other.release()) {}

    /**
     *  Calls unref() on the underlying object pointer.
     */
    ~rcp() {
        safe_unref(m_ptr);
    }

    rcp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }

    rcp<T>& operator=(const rcp<T>& other) {
        if (this != &other) {
            this->reset(safe_ref(other.get()));
        }
        return *this;
    }

    rcp<T>& operator=(rcp<T>&& other) {
        this->reset(other.release());
        return *this;
    }

    T& operator*() const {
        assert(this->get() != nullptr);
        return *this->get();
    }

    explicit operator bool() const { return this->get() != nullptr; }

    T* get() const { return m_ptr; }
    T* operator->() const { return m_ptr; }

    void reset(T* ptr = nullptr) {
        // Calling m_ptr->unref() may call this->~() or this->reset(T*).
        // http://wg21.cmeerw.net/lwg/issue998
        // http://wg21.cmeerw.net/lwg/issue2262
        T* oldPtr = m_ptr;
        m_ptr = ptr;
        safe_unref(oldPtr);
    }

    T* release() {
        T* ptr = m_ptr;
        m_ptr = nullptr;
        return ptr;
    }

    void swap(rcp<T>& other) {
        std::swap(m_ptr, other.m_ptr);
    }

private:
    T* m_ptr;
};

template <typename T> inline void swap(rcp<T>& a, rcp<T>& b) {
    a.swap(b);
}

// == variants

template <typename T> inline bool operator==(const rcp<T>& a, std::nullptr_t) {
    return !a;
}
template <typename T> inline bool operator==(std::nullptr_t, const rcp<T>& b) {
    return !b;
}
template <typename T, typename U> inline bool operator==(const rcp<T>& a, const rcp<U>& b) {
    return a.get() == b.get();
}

// != variants

template <typename T> inline bool operator!=(const rcp<T>& a, std::nullptr_t) {
    return static_cast<bool>(a);
}
template <typename T> inline bool operator!=(std::nullptr_t, const rcp<T>& b) {
    return static_cast<bool>(b);
}
template <typename T, typename U> inline bool operator!=(const rcp<T>& a, const rcp<U>& b) {
    return a.get() != b.get();
}

} // namespace rive

#endif

