diff --git a/source/tanya/memory/allocator.d b/source/tanya/memory/allocator.d index 3ed0e89..761125d 100644 --- a/source/tanya/memory/allocator.d +++ b/source/tanya/memory/allocator.d @@ -10,8 +10,6 @@ */ module tanya.memory.allocator; -import std.typecons; - /** * Abstract class implementing a basic allocator. */ @@ -63,15 +61,6 @@ interface Allocator * Returns: $(D_KEYWORD true) if successful, $(D_KEYWORD false) otherwise. */ bool expand(ref void[] p, in size_t size) shared nothrow @nogc; - - /** - * Returns $(D Ternary.yes) if no memory is currently allocated from this - * allocator, $(D Ternary.no) if some allocations are currently active, or - * $(D Ternary.unknown) if not supported. - * - * Returns: Whether any memory is currently allocated. - */ - Ternary empty() shared nothrow @nogc; } /** diff --git a/source/tanya/memory/mmappool.d b/source/tanya/memory/mmappool.d index 159f3af..4309053 100644 --- a/source/tanya/memory/mmappool.d +++ b/source/tanya/memory/mmappool.d @@ -11,7 +11,7 @@ module tanya.memory.mmappool; import core.stdc.string; -import std.typecons; +import std.algorithm.comparison; import tanya.memory.allocator; version (Posix) @@ -245,9 +245,12 @@ final class MmapPool : Allocator immutable dataSize = addAlignment(size); immutable delta = dataSize - p.length; - if (block1.next is null || block1.next.size + BlockEntry.sizeof < delta) + if (block1.next is null + || !block1.next.free + || block1.next.size + BlockEntry.sizeof < delta) { - // It is the last block in the region or the next block is too small. + // It is the last block in the region or the next block is too small or not + // free. return false; } if (block1.next.size >= delta + alignment_) @@ -255,9 +258,9 @@ final class MmapPool : Allocator // We should move the start position of the next block. The order may be // important because the old block and the new one can overlap. auto block2 = cast(Block) (p.ptr + dataSize); - block2.free = true; block2.size = block1.next.size - delta; - block2.region = block1.next.region; + block2.free = true; + block2.region = block1.region; block2.next = block1.next.next; block2.prev = block1; @@ -316,31 +319,34 @@ final class MmapPool : Allocator */ bool reallocate(ref void[] p, in size_t size) shared nothrow @nogc { - void[] reallocP; - - if (size == p.length) + if (size == 0) + { + if (deallocate(p)) + { + p = null; + return true; + } + return false; + } + else if (size <= p.length) + { + // Leave the block as is. + p = p.ptr[0 .. size]; + return true; + } + else if (expand(p, size)) { return true; } - else if (size > 0) + // Can't extend, allocate a new block, copy and delete the previous. + void[] reallocP = allocate(size); + if (reallocP is null) { - reallocP = allocate(size); - if (reallocP is null) - { - return false; - } + return false; } - if (p !is null) { - if (size > p.length) - { - reallocP[0..p.length] = p[0..$]; - } - else if (size > 0) - { - reallocP[0..size] = p[0..size]; - } + memcpy(reallocP.ptr, p.ptr, min(p.length, size)); deallocate(p); } p = reallocP; @@ -501,19 +507,6 @@ final class MmapPool : Allocator return initializeRegion(size, head); } - /** - * Returns $(D Ternary.yes) if no memory is currently allocated from this - * allocator, $(D Ternary.no) if some allocations are currently active, or - * $(D Ternary.unknown) if not supported. - * - * Returns: Whether any memory is currently allocated. - */ - Ternary empty() shared pure nothrow @safe @nogc - { - // MmapPool always owns some memory because it allocates itself. - return Ternary.no; - } - /* * Params: * x = Space to be aligned.