/*
 * 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(implicit)
            : 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
