#pragma once

#include <util/memory/smallobj.h>
#include <util/memory/mmapalloc.h>
#include <util/generic/vector.h>
#include <util/generic/ptr.h>
#include <util/generic/bitops.h>
#include <util/generic/array_ref.h>
#include <util/generic/singleton.h>

#include <util/stream/output.h>

namespace NSrvKernel {
    template <class T>
    struct TBigObj {
        size_t AdditionalLength() const noexcept {
            return *(reinterpret_cast<const size_t*>(static_cast<const T*>(this)) - 1);
        }

        void* AdditionalData() const noexcept {
            return const_cast<void*>(reinterpret_cast<const void*>(static_cast<const T*>(this) + 1));
        }

        void* operator new(size_t len, size_t add) {
            const size_t overhead = GetOverhead(len);
            size_t* const ret = reinterpret_cast<size_t*>(malloc(add + overhead));

            *ret = add;

            return ret + 1;
        }

        void operator delete(void* ptr) noexcept {
            Del(ptr);
        }

        void operator delete(void* ptr, size_t) noexcept {
            Del(ptr);
        }

        void operator delete(void* ptr, size_t, size_t) noexcept {
            Del(ptr);
        }

        static void Del(void* ptr) noexcept {
            free(reinterpret_cast<void*>(reinterpret_cast<size_t*>(ptr) - 1));
        }

        static size_t GetOverhead(size_t len) noexcept {
            return len + sizeof(size_t);
        }
    };

    class TGoldenRatioGrowPolicy : public TMemoryPool::IGrowPolicy {
    public:
        size_t Next(size_t prev) const noexcept override {
            return prev * 1.62;
        }
    };
}
