/*
 * Copyright 2012, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ANDROID_LINEARALLOCATOR_H
#define ANDROID_LINEARALLOCATOR_H

#include <stddef.h>
#include <type_traits>

#include <vector>

namespace android {
namespace uirenderer {

/**
 * A memory manager that internally allocates multi-kbyte buffers for placing objects in. It avoids
 * the overhead of malloc when many objects are allocated. It is most useful when creating many
 * small objects with a similar lifetime, and doesn't add significant overhead for large
 * allocations.
 */
class LinearAllocator {
public:
    LinearAllocator();
    ~LinearAllocator();

    /**
     * Reserves and returns a region of memory of at least size 'size', aligning as needed.
     * Typically this is used in an object's overridden new() method or as a replacement for malloc.
     *
     * The lifetime of the returned buffers is tied to that of the LinearAllocator. If calling
     * delete() on an object stored in a buffer is needed, it should be overridden to use
     * rewindIfLastAlloc()
     *
     * Note that unlike create, for alloc the type is purely for compile-time error
     * checking and does not affect size.
     */
    template <class T>
    void* alloc(size_t size) {
        static_assert(std::is_trivially_destructible<T>::value,
                      "Error, type is non-trivial! did you mean to use create()?");
        return allocImpl(size);
    }

    /**
     * Allocates an instance of the template type with the given construction parameters
     * and adds it to the automatic destruction list.
     */
    template <class T, typename... Params>
    T* create(Params&&... params) {
        T* ret = new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...);
        if (!std::is_trivially_destructible<T>::value) {
            auto dtor = [](void* ret) { ((T*)ret)->~T(); };
            addToDestructionList(dtor, ret);
        }
        return ret;
    }

    template <class T, typename... Params>
    T* create_trivial(Params&&... params) {
        static_assert(std::is_trivially_destructible<T>::value,
                      "Error, called create_trivial on a non-trivial type");
        return new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...);
    }

    template <class T>
    T* create_trivial_array(int count) {
        static_assert(std::is_trivially_destructible<T>::value,
                      "Error, called create_trivial_array on a non-trivial type");
        return reinterpret_cast<T*>(allocImpl(sizeof(T) * count));
    }

    /**
     * Attempt to deallocate the given buffer, with the LinearAllocator attempting to rewind its
     * state if possible.
     */
    void rewindIfLastAlloc(void* ptr, size_t allocSize);

    /**
     * Same as rewindIfLastAlloc(void*, size_t)
     */
    template <class T>
    void rewindIfLastAlloc(T* ptr) {
        rewindIfLastAlloc((void*)ptr, sizeof(T));
    }

    /**
     * Dump memory usage statistics to the log (allocated and wasted space)
     */
    void dumpMemoryStats(const char* prefix = "");

    /**
     * The number of bytes used for buffers allocated in the LinearAllocator (does not count space
     * wasted)
     */
    size_t usedSize() const { return mTotalAllocated - mWastedSpace; }

private:
    LinearAllocator(const LinearAllocator& other);

    class Page;
    typedef void (*Destructor)(void* addr);
    struct DestructorNode {
        Destructor dtor;
        void* addr;
        DestructorNode* next = nullptr;
    };

    void* allocImpl(size_t size);

    void addToDestructionList(Destructor, void* addr);
    void runDestructorFor(void* addr);
    Page* newPage(size_t pageSize);
    bool fitsInCurrentPage(size_t size);
    void ensureNext(size_t size);
    void* start(Page* p);
    void* end(Page* p);

    size_t mPageSize;
    size_t mMaxAllocSize;
    void* mNext;
    Page* mCurrentPage;
    Page* mPages;
    DestructorNode* mDtorList = nullptr;

    // Memory usage tracking
    size_t mTotalAllocated;
    size_t mWastedSpace;
    size_t mPageCount;
    size_t mDedicatedPageCount;
};

template <class T>
class LinearStdAllocator {
public:
    typedef T value_type;  // needed to implement std::allocator
    typedef T* pointer;    // needed to implement std::allocator

    explicit LinearStdAllocator(LinearAllocator& allocator) : linearAllocator(allocator) {}
    LinearStdAllocator(const LinearStdAllocator& other) : linearAllocator(other.linearAllocator) {}
    ~LinearStdAllocator() {}

    // rebind marks that allocators can be rebound to different types
    template <class U>
    struct rebind {
        typedef LinearStdAllocator<U> other;
    };
    // enable allocators to be constructed from other templated types
    template <class U>
    LinearStdAllocator(const LinearStdAllocator<U>& other)  // NOLINT(google-explicit-constructor)
            : linearAllocator(other.linearAllocator) {}

    T* allocate(size_t num, const void* = 0) {
        return (T*)(linearAllocator.alloc<void*>(num * sizeof(T)));
    }

    void deallocate(pointer p, size_t num) {
        // attempt to rewind, but no guarantees
        linearAllocator.rewindIfLastAlloc(p, num * sizeof(T));
    }

    // public so template copy constructor can access
    LinearAllocator& linearAllocator;
};

// return that all specializations of LinearStdAllocator are interchangeable
template <class T1, class T2>
bool operator==(const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) {
    return true;
}
template <class T1, class T2>
bool operator!=(const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) {
    return false;
}

template <class T>
class LsaVector : public std::vector<T, LinearStdAllocator<T>> {
public:
    explicit LsaVector(const LinearStdAllocator<T>& allocator)
            : std::vector<T, LinearStdAllocator<T>>(allocator) {}
};

};  // namespace uirenderer
};  // namespace android

#endif  // ANDROID_LINEARALLOCATOR_H
