//
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// RingBufferAllocator.h:
//    Classes used to implement ring buffer allocators.
//

#ifndef COMMON_RING_BUFFER_ALLOCATOR_H_
#define COMMON_RING_BUFFER_ALLOCATOR_H_

#include "angleutils.h"
#include "common/debug.h"

#include <atomic>

namespace angle
{

static constexpr uint32_t kMinRingBufferAllocationCapacity = 1024;
static constexpr uint32_t kDefaultDecaySpeedFactor         = 10;

// Only called from RingBufferAllocator::allocate(). Other function may also change the fragment.
class RingBufferAllocateListener
{
  public:
    virtual void onRingBufferNewFragment() = 0;
    virtual void onRingBufferFragmentEnd() = 0;

  protected:
    ~RingBufferAllocateListener() = default;
};

class RingBufferAllocatorCheckPoint final
{
  public:
    void reset() { *this = {}; }
    bool valid() const { return (mReleasePtr != nullptr); }

  private:
    friend class RingBufferAllocator;
    uint64_t mBufferId   = 0;
    uint8_t *mReleasePtr = nullptr;
};

class RingBufferAllocatorBuffer final
{
  public:
    static constexpr uint32_t kBaseOffset = alignof(std::max_align_t);

    void resize(uint32_t size) { mStorage.resize(size + kBaseOffset); }
    uint8_t *data() { return mStorage.data() + kBaseOffset; }

    uint8_t *decClamped(uint8_t *ptr, uint32_t offset) const
    {
        ASSERT(ptr >= mStorage.data() + kBaseOffset && ptr <= mStorage.data() + mStorage.size());
        return ptr - std::min(offset, static_cast<uint32_t>(ptr - mStorage.data()));
    }

    uint64_t getId() const { return mId; }
    void resetId() { mId = 0; }
    void incrementId() { ++mId; }

    bool isEmpty() const { return mStorage.empty(); }

  private:
    uint64_t mId = 0;
    std::vector<uint8_t> mStorage;
};

class RingBufferAllocator final : angle::NonCopyable
{
  public:
    RingBufferAllocator() = default;
    RingBufferAllocator(RingBufferAllocator &&other);
    RingBufferAllocator &operator=(RingBufferAllocator &&other);

    void reset();
    bool valid() const { return (getPointer() != nullptr); }

    void setListener(RingBufferAllocateListener *listener);

    void setDecaySpeedFactor(uint32_t decaySpeedFactor);

    void setFragmentReserve(uint32_t reserve);

    uint8_t *allocate(uint32_t size)
    {
        ASSERT(valid());
        if (ANGLE_LIKELY(mFragmentEndR - mDataEnd >= static_cast<ptrdiff_t>(size)))
        {
            uint8_t *const result = mDataEnd;
            mDataEnd              = result + size;
            return result;
        }
        return allocateInNewFragment(size);
    }

    uint8_t *getPointer() const { return mDataEnd; }
    uint32_t getFragmentSize() const
    {
        ASSERT(mFragmentEnd >= mDataEnd);
        return static_cast<uint32_t>(mFragmentEnd - mDataEnd);
    }

    RingBufferAllocatorCheckPoint getReleaseCheckPoint() const;
    void release(const RingBufferAllocatorCheckPoint &checkPoint);

  private:
    void release(uint8_t *releasePtr);
    uint32_t getNumAllocatedInBuffer() const;
    void resetPointers();

    uint8_t *allocateInNewFragment(uint32_t size);
    void resize(uint32_t newCapacity);

    RingBufferAllocateListener *mListener = nullptr;

    std::vector<RingBufferAllocatorBuffer> mOldBuffers;
    RingBufferAllocatorBuffer mBuffer;
    uint8_t *mDataBegin       = nullptr;
    uint8_t *mDataEnd         = nullptr;
    uint8_t *mFragmentEnd     = nullptr;
    uint8_t *mFragmentEndR    = nullptr;
    uint32_t mFragmentReserve = 0;

    uint32_t mMinCapacity      = 0;
    uint32_t mCurrentCapacity  = 0;
    uint32_t mAllocationMargin = 0;

    // 1 - fastest decay speed.
    // 2 - 2x slower than fastest, and so on.
    uint32_t mDecaySpeedFactor = 0;
};

class SharedRingBufferAllocatorCheckPoint final : angle::NonCopyable
{
  public:
    void releaseAndUpdate(RingBufferAllocatorCheckPoint *newValue);

  private:
    friend class SharedRingBufferAllocator;
    RingBufferAllocatorCheckPoint pop();
    std::mutex mMutex;
    RingBufferAllocatorCheckPoint mValue;

#if defined(ANGLE_ENABLE_ASSERTS)
    std::atomic<uint32_t> mRefCount{1};
#endif
};

class SharedRingBufferAllocator final : angle::NonCopyable
{
  public:
    SharedRingBufferAllocator();
    ~SharedRingBufferAllocator();

    RingBufferAllocator &get() { return mAllocator; }

    // Once shared - always shared
    bool isShared() const { return mSharedCP != nullptr; }

    // Once acquired must be released with releaseAndUpdate().
    SharedRingBufferAllocatorCheckPoint *acquireSharedCP();
    void releaseToSharedCP();

  private:
    RingBufferAllocator mAllocator;
    SharedRingBufferAllocatorCheckPoint *mSharedCP = nullptr;
};

}  // namespace angle

#endif  // COMMON_RING_BUFFER_ALLOCATOR_H_
