Make allocators pure.
* Methods allocating/deallocating memory are pure.
* Allocator.instance is pure (once initialized, it always returns
  the same instance).
* defaultAllocator getter property is pure (should be set at the
  beginning, and always return the same instance after that).
This commit is contained in:
2017-07-13 16:01:21 +02:00
parent 839c740cb1
commit 657f4a60d5
4 changed files with 93 additions and 52 deletions

View File

@ -167,7 +167,7 @@ final class MmapPool : Allocator
- MmapPool.alignment_
- BlockEntry.sizeof * 2
- RegionEntry.sizeof
- pageSize;
- MmapPool.instance.pageSize;
assert(MmapPool.instance.allocate(tooMuchMemory) is null);
assert(MmapPool.instance.allocate(size_t.max) is null);
@ -471,46 +471,52 @@ final class MmapPool : Allocator
MmapPool.instance.deallocate(p);
}
/**
* Static allocator instance and initializer.
*
* Returns: Global $(D_PSYMBOL MmapPool) instance.
*/
static @property ref shared(MmapPool) instance() nothrow @nogc
static private shared(MmapPool) instantiate() nothrow @nogc
{
if (instance_ is null)
{
// Get system dependend page size.
version (Posix)
{
pageSize_ = sysconf(_SC_PAGE_SIZE);
if (pageSize_ < 65536)
size_t pageSize = sysconf(_SC_PAGE_SIZE);
if (pageSize < 65536)
{
pageSize_ = pageSize_ * 65536 / pageSize_;
pageSize = pageSize * 65536 / pageSize;
}
}
else version (Windows)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
pageSize_ = si.dwPageSize;
size_t pageSize = si.dwPageSize;
}
const instanceSize = addAlignment(__traits(classInstanceSize,
MmapPool));
Region head; // Will become soon our region list head
void* data = initializeRegion(instanceSize, head);
void* data = initializeRegion(instanceSize, head, pageSize);
if (data !is null)
{
memcpy(data, typeid(MmapPool).initializer.ptr, instanceSize);
instance_ = cast(shared MmapPool) data;
instance_.head = head;
instance_.pageSize = pageSize;
}
}
return instance_;
}
/**
* Static allocator instance and initializer.
*
* Returns: Global $(D_PSYMBOL MmapPool) instance.
*/
static @property shared(MmapPool) instance() pure nothrow @nogc
{
return (cast(GetPureInstance!MmapPool) &instantiate)();
}
///
nothrow unittest
{
@ -526,10 +532,12 @@ final class MmapPool : Allocator
*
* Returns: A pointer to the data.
*/
private static void* initializeRegion(const size_t size, ref Region head)
private static void* initializeRegion(const size_t size,
ref Region head,
const size_t pageSize)
pure nothrow @nogc
{
const regionSize = calculateRegionSize(size);
const regionSize = calculateRegionSize(size, pageSize);
if (regionSize < size)
{
return null;
@ -578,7 +586,7 @@ final class MmapPool : Allocator
private void* initializeRegion(const size_t size) shared pure nothrow @nogc
{
return initializeRegion(size, head);
return initializeRegion(size, this.head, this.pageSize);
}
/*
@ -594,11 +602,13 @@ final class MmapPool : Allocator
/*
* Params:
* x = Required space.
* x = Required space.
* pageSize = Page size.
*
* Returns: Minimum region size (a multiple of $(D_PSYMBOL pageSize)).
*/
private static size_t calculateRegionSize(const size_t x)
private static size_t calculateRegionSize(ref const size_t x,
ref const size_t pageSize)
pure nothrow @safe @nogc
{
return (x + RegionEntry.sizeof + BlockEntry.sizeof * 2)
@ -618,18 +628,10 @@ final class MmapPool : Allocator
assert(MmapPool.instance.alignment == MmapPool.alignment_);
}
private static @property size_t pageSize() pure nothrow @trusted @nogc
{
const pageSize = function size_t() nothrow @safe @nogc {
return pageSize_;
};
return (cast(size_t function() pure nothrow @safe @nogc) pageSize)();
}
private enum uint alignment_ = 8;
private shared static MmapPool instance_;
private shared static size_t pageSize_;
private shared size_t pageSize;
private shared struct RegionEntry
{