summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/tanya/memory/allocator.d11
-rw-r--r--source/tanya/memory/mmappool.d65
2 files changed, 29 insertions, 47 deletions
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 (size > 0)
+ else if (expand(p, size))
{
- reallocP = allocate(size);
- if (reallocP is null)
- {
- return false;
- }
+ return true;
+ }
+ // Can't extend, allocate a new block, copy and delete the previous.
+ void[] reallocP = allocate(size);
+ if (reallocP is null)
+ {
+ 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.