#ifndef memory_hh_INCLUDED #define memory_hh_INCLUDED #include #include #include #include "assert.hh" namespace Kakoune { enum class MemoryDomain { Undefined, String, SharedString, BufferContent, BufferMeta, Options, Highlight, Display, Mapping, Commands, Hooks, Aliases, EnvVars, Faces, Values, Registers, Client, WordDB, Selections, History, Count }; inline const char* domain_name(MemoryDomain domain) { switch (domain) { case MemoryDomain::Undefined: return "Undefined"; case MemoryDomain::String: return "String"; case MemoryDomain::SharedString: return "SharedString"; case MemoryDomain::BufferContent: return "BufferContent"; case MemoryDomain::BufferMeta: return "BufferMeta"; case MemoryDomain::Options: return "Options"; case MemoryDomain::Highlight: return "Highlight"; case MemoryDomain::Display: return "Display"; case MemoryDomain::Mapping: return "Mapping"; case MemoryDomain::Commands: return "Commands"; case MemoryDomain::Hooks: return "Hooks"; case MemoryDomain::WordDB: return "WordDB"; case MemoryDomain::Aliases: return "Aliases"; case MemoryDomain::EnvVars: return "EnvVars"; case MemoryDomain::Faces: return "Faces"; case MemoryDomain::Values: return "Values"; case MemoryDomain::Registers: return "Registers"; case MemoryDomain::Client: return "Client"; case MemoryDomain::Selections: return "Selections"; case MemoryDomain::History: return "History"; case MemoryDomain::Count: break; } kak_assert(false); return ""; } extern size_t domain_allocated_bytes[(size_t)MemoryDomain::Count]; inline void on_alloc(MemoryDomain domain, size_t size) { domain_allocated_bytes[(int)domain] += size; } inline void on_dealloc(MemoryDomain domain, size_t size) { kak_assert(domain_allocated_bytes[(int)domain] >= size); domain_allocated_bytes[(int)domain] -= size; } template struct Allocator { using value_type = T; // TODO: remove that once we have a c++11 compliant stdlib using pointer = T*; using const_pointer = const T*; using reference = T&; using const_reference = const T&; using size_type = std::size_t; using difference_type = std::ptrdiff_t; Allocator() = default; template Allocator(const Allocator&) {} template struct rebind { using other = Allocator; }; T* allocate(size_t n) { size_t size = sizeof(T) * n; on_alloc(domain, size); return reinterpret_cast(::operator new(size)); } void deallocate(T* ptr, size_t n) { size_t size = sizeof(T) * n; on_dealloc(domain, size); ::operator delete(ptr); } template [[gnu::always_inline]] void construct(U* p, Args&&... args) { new ((void*)p) U(std::forward(args)...); } template [[gnu::always_inline]] void destroy(U* p) { p->~U(); } }; template bool operator==(const Allocator& lhs, const Allocator& rhs) { return d1 == d2; } template bool operator!=(const Allocator& lhs, const Allocator& rhs) { return d1 != d2; } template struct TypeDomain { static constexpr MemoryDomain domain() { return TypeDomain::helper((T*)nullptr); } private: template static decltype(U::Domain) constexpr helper(U*) { return U::Domain; } static constexpr MemoryDomain helper(...) { return MemoryDomain::Undefined; } }; template struct UseMemoryDomain { static constexpr MemoryDomain Domain = d; static void* operator new(size_t size) { on_alloc(Domain, size); return ::operator new(size); } static void* operator new(size_t size, void* ptr) { return ::operator new(size, ptr); } static void operator delete(void* ptr, size_t size) { on_dealloc(Domain, size); ::operator delete(ptr); } }; } #endif // memory_hh_INCLUDED