// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <zircon/assert.h>
#include <zircon/compiler.h>
#include <fbl/atomic.h>
#include <fbl/canary.h>

namespace fbl {
namespace internal {

template <bool Enabled>
class AdoptionValidator;

// This will catch:
// - Double-adoptions
// - AddRef/Release without adopting first
// - Wrapping bad pointers
// - Re-wrapping raw pointers to destroyed objects
template <>
class AdoptionValidator<true> {
public:
    ~AdoptionValidator() {
        magic_ = 0;
    }

    void Adopt() const {
        AssertMagic(kStartingMagic);
        magic_ = kAdoptedMagic;
    }
    void ValidateAddRef() const {
        AssertMagic(kAdoptedMagic);
    }
    void ValidateRelease() const {
        AssertMagic(kAdoptedMagic);
    }

private:
    void AssertMagic(const uint32_t expected) const {
        ZX_DEBUG_ASSERT_MSG(magic_ == expected,
                            "Invalid magic (expect: 0x%02x, got: 0x%02x)\n",
                            static_cast<unsigned int>(expected),
                            static_cast<unsigned int>(magic_));
    }

    // The object has been constructed, but not yet adopted or destroyed.
    static constexpr uint32_t kStartingMagic = fbl::magic("RcST");

    // The object has been constructed and adopted, but not destroyed.
    static constexpr uint32_t kAdoptedMagic = fbl::magic("RcAD");

    mutable volatile uint32_t magic_ = kStartingMagic;
};

template <>
class AdoptionValidator<false> {
public:
    void Adopt() const {}
    void ValidateAddRef() const {}
    void ValidateRelease() const {}
};

template <bool EnableAdoptionValidator>
class RefCountedBase {
protected:
    constexpr RefCountedBase()
        : ref_count_(1) {}
    ~RefCountedBase() {}
    void AddRef() const {
        adoption_validator_.ValidateAddRef();
        const int rc = ref_count_.fetch_add(1, memory_order_relaxed);
        if (EnableAdoptionValidator) {
            // This assertion will fire if someone calls AddRef() on a
            // ref-counted object that has reached ref_count_ == 0 but has not
            // been destroyed yet. This could happen by manually calling
            // AddRef(), or re-wrapping such a pointer with WrapRefPtr() or
            // RefPtr<T>(T*) (both of which call AddRef()). If the object has
            // already been destroyed, the magic check in
            // adoption_validator_.ValidateAddRef() should have caught it before
            // this point.
            ZX_DEBUG_ASSERT_MSG(rc >= 1, "count %d < 1\n", rc);
        }
    }

    // This method should not be used. See MakeRefPtrUpgradeFromRaw()
    // for details in the proper use of this method. The actual job of
    // this function is to atomically increment the refcount if the
    // refcount is greater than zero.
    //
    // This method returns false if the object was found with refcount
    // of zero and refcount was unmodified and true if the refcount
    // was not zero and it was incremented.
    //
    // The procedure used is the while-CAS loop with the advantage that
    // compare_exchange on failure updates |old| on failure (to exchange)
    // so the loop does not have to do a separate load.
    //
    bool AddRefMaybeInDestructor() {
        int old = ref_count_.load(memory_order_acquire);
        do {
            if (old == 0)
                return false;
        } while (!ref_count_.compare_exchange_weak(
            &old, old + 1, memory_order_acquire, memory_order_acquire));
        return true;
    }

    // Returns true if the object should self-delete.
    bool Release() const __WARN_UNUSED_RESULT {
        adoption_validator_.ValidateRelease();
        const int rc = ref_count_.fetch_sub(1, memory_order_release);
        if (EnableAdoptionValidator) {
            // This assertion will fire if someone manually calls Release()
            // on a ref-counted object too many times.
            ZX_DEBUG_ASSERT_MSG(rc >= 1, "count %d < 1\n", rc);
        }
        if (rc == 1) {
            atomic_thread_fence(memory_order_acquire);
            return true;
        }
        return false;
    }

    void Adopt() const {
        adoption_validator_.Adopt();
    }

    // Current ref count. Only to be used for debugging purposes.
    int ref_count_debug() const {
        return ref_count_.load(memory_order_relaxed);
    }

private:
    mutable fbl::atomic_int ref_count_;
    AdoptionValidator<EnableAdoptionValidator> adoption_validator_;
};

} // namespace internal
} // namespace fbl
