2015-01-07 22:29:31 +03:00
|
|
|
#ifndef memory_hh_INCLUDED
|
|
|
|
#define memory_hh_INCLUDED
|
|
|
|
|
2015-01-12 23:03:52 +03:00
|
|
|
#include <cstddef>
|
2015-01-14 02:54:58 +03:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <new>
|
2015-01-14 01:56:51 +03:00
|
|
|
#include <utility>
|
2015-01-07 22:29:31 +03:00
|
|
|
|
|
|
|
#include "assert.hh"
|
|
|
|
|
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
|
|
|
enum class MemoryDomain
|
|
|
|
{
|
|
|
|
Undefined,
|
|
|
|
String,
|
|
|
|
InternedString,
|
|
|
|
BufferContent,
|
|
|
|
BufferMeta,
|
2015-01-12 16:24:30 +03:00
|
|
|
Options,
|
|
|
|
Highlight,
|
2015-01-12 16:45:44 +03:00
|
|
|
Mapping,
|
|
|
|
Commands,
|
|
|
|
Hooks,
|
2015-01-12 22:46:40 +03:00
|
|
|
WordDB,
|
|
|
|
Count
|
2015-01-07 22:29:31 +03:00
|
|
|
};
|
|
|
|
|
2015-01-12 22:46:40 +03:00
|
|
|
inline const char* domain_name(MemoryDomain domain)
|
2015-01-07 22:29:31 +03:00
|
|
|
{
|
2015-01-12 22:46:40 +03:00
|
|
|
switch (domain)
|
|
|
|
{
|
|
|
|
case MemoryDomain::Undefined: return "Undefined";
|
|
|
|
case MemoryDomain::String: return "String";
|
|
|
|
case MemoryDomain::InternedString: return "InternedString";
|
|
|
|
case MemoryDomain::BufferContent: return "BufferContent";
|
|
|
|
case MemoryDomain::BufferMeta: return "BufferMeta";
|
|
|
|
case MemoryDomain::Options: return "Options";
|
|
|
|
case MemoryDomain::Highlight: return "Highlight";
|
|
|
|
case MemoryDomain::Mapping: return "Mapping";
|
|
|
|
case MemoryDomain::Commands: return "Commands";
|
|
|
|
case MemoryDomain::Hooks: return "Hooks";
|
|
|
|
case MemoryDomain::WordDB: return "WordDB";
|
|
|
|
case MemoryDomain::Count: break;
|
|
|
|
}
|
|
|
|
kak_assert(false);
|
|
|
|
return "";
|
|
|
|
}
|
2015-01-07 22:29:31 +03:00
|
|
|
|
2015-01-12 22:46:40 +03:00
|
|
|
extern size_t domain_allocated_bytes[(size_t)MemoryDomain::Count];
|
2015-01-07 22:29:31 +03:00
|
|
|
|
|
|
|
template<typename T, MemoryDomain domain>
|
|
|
|
struct Allocator
|
|
|
|
{
|
|
|
|
using value_type = T;
|
2015-01-09 16:57:21 +03:00
|
|
|
// 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;
|
2015-01-07 22:29:31 +03:00
|
|
|
|
|
|
|
Allocator() = default;
|
|
|
|
template<typename U>
|
|
|
|
Allocator(const Allocator<U, domain>&) {}
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
struct rebind { using other = Allocator<U, domain>; };
|
|
|
|
|
|
|
|
T* allocate(size_t n)
|
|
|
|
{
|
|
|
|
size_t size = sizeof(T) * n;
|
2015-01-12 22:46:40 +03:00
|
|
|
domain_allocated_bytes[(int)domain] += size;
|
2015-01-07 22:29:31 +03:00
|
|
|
return reinterpret_cast<T*>(malloc(size));
|
|
|
|
}
|
|
|
|
|
|
|
|
void deallocate(T* ptr, size_t n)
|
|
|
|
{
|
|
|
|
size_t size = sizeof(T) * n;
|
2015-01-12 22:46:40 +03:00
|
|
|
kak_assert(domain_allocated_bytes[(int)domain] >= size);
|
|
|
|
domain_allocated_bytes[(int)domain] -= size;
|
2015-01-07 22:29:31 +03:00
|
|
|
free(ptr);
|
|
|
|
}
|
2015-01-14 01:56:51 +03:00
|
|
|
|
|
|
|
template<class U, class... Args>
|
|
|
|
void construct(U* p, Args&&... args)
|
|
|
|
{
|
|
|
|
new (p) U(std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class U>
|
|
|
|
void destroy(U* p) { p->~U(); }
|
2015-01-07 22:29:31 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T1, MemoryDomain d1, typename T2, MemoryDomain d2>
|
|
|
|
bool operator==(const Allocator<T1, d1>& lhs, const Allocator<T2, d2>& rhs)
|
|
|
|
{
|
|
|
|
return d1 == d2;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T1, MemoryDomain d1, typename T2, MemoryDomain d2>
|
|
|
|
bool operator!=(const Allocator<T1, d1>& lhs, const Allocator<T2, d2>& rhs)
|
|
|
|
{
|
|
|
|
return d1 != d2;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // memory_hh_INCLUDED
|