/*
 * Copyright 2014 Google, Inc
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkSmallAllocator_DEFINED
#define SkSmallAllocator_DEFINED

#include "SkTDArray.h"
#include "SkTypes.h"

// Used by SkSmallAllocator to call the destructor for objects it has
// allocated.
template<typename T> void destroyT(void* ptr) {
   static_cast<T*>(ptr)->~T();
}

/*
 *  Template class for allocating small objects without additional heap memory
 *  allocations. kMaxObjects is a hard limit on the number of objects that can
 *  be allocated using this class. After that, attempts to create more objects
 *  with this class will assert and return NULL.
 *  kTotalBytes is the total number of bytes provided for storage for all
 *  objects created by this allocator. If an object to be created is larger
 *  than the storage (minus storage already used), it will be allocated on the
 *  heap. This class's destructor will handle calling the destructor for each
 *  object it allocated and freeing its memory.
 */
template<uint32_t kMaxObjects, size_t kTotalBytes>
class SkSmallAllocator : SkNoncopyable {
public:
    SkSmallAllocator()
    : fStorageUsed(0)
    , fNumObjects(0)
    {}

    ~SkSmallAllocator() {
        // Destruct in reverse order, in case an earlier object points to a
        // later object.
        while (fNumObjects > 0) {
            fNumObjects--;
            Rec* rec = &fRecs[fNumObjects];
            rec->fKillProc(rec->fObj);
            // Safe to do if fObj is in fStorage, since fHeapStorage will
            // point to NULL.
            sk_free(rec->fHeapStorage);
        }
    }

    /*
     *  Create a new object of type T. Its lifetime will be handled by this
     *  SkSmallAllocator.
     *  Each version behaves the same but takes a different number of
     *  arguments.
     *  Note: If kMaxObjects have been created by this SkSmallAllocator, NULL
     *  will be returned.
     */
    template<typename T>
    T* createT() {
        void* buf = this->reserveT<T>();
        if (NULL == buf) {
            return NULL;
        }
        SkNEW_PLACEMENT(buf, T);
        return static_cast<T*>(buf);
    }

    template<typename T, typename A1> T* createT(const A1& a1) {
        void* buf = this->reserveT<T>();
        if (NULL == buf) {
            return NULL;
        }
        SkNEW_PLACEMENT_ARGS(buf, T, (a1));
        return static_cast<T*>(buf);
    }

    template<typename T, typename A1, typename A2>
    T* createT(const A1& a1, const A2& a2) {
        void* buf = this->reserveT<T>();
        if (NULL == buf) {
            return NULL;
        }
        SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2));
        return static_cast<T*>(buf);
    }

    template<typename T, typename A1, typename A2, typename A3>
    T* createT(const A1& a1, const A2& a2, const A3& a3) {
        void* buf = this->reserveT<T>();
        if (NULL == buf) {
            return NULL;
        }
        SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3));
        return static_cast<T*>(buf);
    }

    template<typename T, typename A1, typename A2, typename A3, typename A4>
    T* createT(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
        void* buf = this->reserveT<T>();
        if (NULL == buf) {
            return NULL;
        }
        SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3, a4));
        return static_cast<T*>(buf);
    }

    /*
     *  Reserve a specified amount of space (must be enough space for one T).
     *  The space will be in fStorage if there is room, or on the heap otherwise.
     *  Either way, this class will call ~T() in its destructor and free the heap
     *  allocation if necessary.
     *  Unlike createT(), this method will not call the constructor of T.
     */
    template<typename T> void* reserveT(size_t storageRequired = sizeof(T)) {
        SkASSERT(fNumObjects < kMaxObjects);
        SkASSERT(storageRequired >= sizeof(T));
        if (kMaxObjects == fNumObjects) {
            return NULL;
        }
        const size_t storageRemaining = SkAlign4(kTotalBytes) - fStorageUsed;
        storageRequired = SkAlign4(storageRequired);
        Rec* rec = &fRecs[fNumObjects];
        if (storageRequired > storageRemaining) {
            // Allocate on the heap. Ideally we want to avoid this situation,
            // but we're not sure we can catch all callers, so handle it but
            // assert false in debug mode.
            SkASSERT(false);
            rec->fStorageSize = 0;
            rec->fHeapStorage = sk_malloc_throw(storageRequired);
            rec->fObj = static_cast<void*>(rec->fHeapStorage);
        } else {
            // There is space in fStorage.
            rec->fStorageSize = storageRequired;
            rec->fHeapStorage = NULL;
            SkASSERT(SkIsAlign4(fStorageUsed));
            rec->fObj = static_cast<void*>(fStorage + (fStorageUsed / 4));
            fStorageUsed += storageRequired;
        }
        rec->fKillProc = destroyT<T>;
        fNumObjects++;
        return rec->fObj;
    }

    /*
     *  Free the memory reserved last without calling the destructor.
     *  Can be used in a nested way, i.e. after reserving A and B, calling
     *  freeLast once will free B and calling it again will free A.
     */
    void freeLast() {
        SkASSERT(fNumObjects > 0);
        Rec* rec = &fRecs[fNumObjects - 1];
        sk_free(rec->fHeapStorage);
        fStorageUsed -= rec->fStorageSize;

        fNumObjects--;
    }

private:
    struct Rec {
        size_t fStorageSize;  // 0 if allocated on heap
        void*  fObj;
        void*  fHeapStorage;
        void   (*fKillProc)(void*);
    };

    // Number of bytes used so far.
    size_t              fStorageUsed;
    // Pad the storage size to be 4-byte aligned.
    uint32_t            fStorage[SkAlign4(kTotalBytes) >> 2];
    uint32_t            fNumObjects;
    Rec                 fRecs[kMaxObjects];
};

#endif // SkSmallAllocator_DEFINED
