summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/tanya/container/vector.d77
-rw-r--r--source/tanya/memory/allocator.d7
-rw-r--r--source/tanya/memory/mmappool.d42
3 files changed, 76 insertions, 50 deletions
diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d
index 113a9ad..b86028f 100644
--- a/source/tanya/container/vector.d
+++ b/source/tanya/container/vector.d
@@ -117,7 +117,7 @@ private struct Range(E)
in
{
assert(i <= j);
- assert(j < length);
+ assert(j <= length);
}
body
{
@@ -128,7 +128,7 @@ private struct Range(E)
in
{
assert(i <= j);
- assert(j < length);
+ assert(j <= length);
}
body
{
@@ -445,7 +445,7 @@ struct Vector(T)
assert(!overflow);
void[] buf = vector[0 .. capacity_];
- if (!allocator.expand(buf, byteSize))
+ if (!allocator.reallocateInPlace(buf, byteSize))
{
buf = allocator.allocate(byteSize);
if (buf is null)
@@ -494,11 +494,16 @@ struct Vector(T)
*/
void shrink(in size_t size) @trusted
{
- auto n = max(length, size);
+ if (capacity_ <= size)
+ {
+ return;
+ }
+ immutable n = max(length, size);
void[] buf = vector[0 .. capacity_];
- allocator.reallocate(buf, n * T.sizeof);
- vector = cast(T*) buf;
- capacity_ = n;
+ if (allocator.reallocateInPlace(buf, n * T.sizeof))
+ {
+ capacity_ = n;
+ }
}
///
@@ -733,16 +738,22 @@ struct Vector(T)
}
/// Ditto.
- Range!T opIndexAssign()(auto ref T value)
+ Range!T opIndexAssign(T value)
+ {
+ return opSliceAssign(value, 0, length);
+ }
+
+ /// Ditto.
+ Range!T opIndexAssign(ref T value)
{
return opSliceAssign(value, 0, length);
}
/**
- * Assigns a range. The range should have the same length as the vector.
+ * Assigns a range or a static array.
*
* Params:
- * R = Range type.
+ * R = Range type or static array length.
* value = Value.
*
* Returns: Assigned value.
@@ -750,15 +761,20 @@ struct Vector(T)
* Precondition: $(D_INLINECODE length == value.length)
*/
Range!T opIndexAssign(R)(R value)
- if ((!isInfinite!R && isInputRange!R
+ if (!isInfinite!R && isInputRange!R
&& isImplicitlyConvertible!(ElementType!R, T))
- || isStaticArray!R && is(ElementType!R == T))
{
- return opSliceAssign(value, 0, length);
+ return opSliceAssign!R(value, 0, length);
+ }
+
+ /// Ditto.
+ Range!T opIndexAssign(size_t R)(T[R] value)
+ {
+ return opSliceAssign!R(value, 0, length);
}
///
- unittest
+ @nogc unittest
{
auto v1 = Vector!int([12, 1, 7]);
@@ -1073,7 +1089,7 @@ struct Vector(T)
in
{
assert(i <= j);
- assert(j <= length_);
+ assert(j <= length);
}
body
{
@@ -1128,7 +1144,9 @@ struct Vector(T)
* Slicing assignment.
*
* Params:
- * value = New value (single value or input range).
+ * R = Type of the assigned slice or length of the static array should be
+ * assigned.
+ * value = New value (single value, input range or static array).
* i = Slice start.
* j = Slice end.
*
@@ -1137,43 +1155,48 @@ struct Vector(T)
* Precondition: $(D_INLINECODE i <= j && j <= length
* && value.length == j - i)
*/
- Range!T opSliceAssign(ref T value, in size_t i, in size_t j)
+ Range!T opSliceAssign(R)(R value, in size_t i, in size_t j)
+ if (!isInfinite!R && isInputRange!R
+ && isImplicitlyConvertible!(ElementType!R, T))
in
{
assert(i <= j);
assert(j <= length);
+ assert(j - i == walkLength(value));
}
body
{
- fill((() @trusted => vector[i .. j])(), value);
+ copy(value, opSlice(i, j));
return opSlice(i, j);
}
/// Ditto.
- Range!T opSliceAssign(T value, in size_t i, in size_t j)
+ Range!T opSliceAssign(size_t R)(T[R] value, in size_t i, in size_t j)
{
- return opSliceAssign(value, i, j);
+ return opSliceAssign!(T[])(value[], i, j);
}
/// Ditto.
- Range!T opSliceAssign(R)(R value, in size_t i, in size_t j)
- if ((!isInfinite!R && isInputRange!R
- && isImplicitlyConvertible!(ElementType!R, T))
- || isStaticArray!R && is(ElementType!R == T))
+ Range!T opSliceAssign(ref T value, in size_t i, in size_t j)
in
{
assert(i <= j);
assert(j <= length);
- assert(j - i == walkLength(value));
}
body
{
- copy(value, (() @trusted => vector[i .. j])());
+ fill(opSlice(i, j), value);
return opSlice(i, j);
}
+ /// Ditto.
+ Range!T opSliceAssign(T value, in size_t i, in size_t j)
+ {
+ return opSliceAssign(value, i, j);
+ }
+
///
- @safe unittest
+ @nogc @safe unittest
{
auto v1 = Vector!int([3, 3, 3]);
auto v2 = Vector!int([1, 2]);
diff --git a/source/tanya/memory/allocator.d b/source/tanya/memory/allocator.d
index 761125d..930a934 100644
--- a/source/tanya/memory/allocator.d
+++ b/source/tanya/memory/allocator.d
@@ -52,7 +52,10 @@ interface Allocator
bool reallocate(ref void[] p, in size_t size) shared nothrow @nogc;
/**
- * Expands a memory block in place.
+ * Reallocates a memory block in place if possible or returns
+ * $(D_KEYWORD false). This function cannot be used to allocate or
+ * deallocate memory, so if $(D_PARAM p) is $(D_KEYWORD null) or
+ * $(D_PARAM size) is `0`, it should return $(D_KEYWORD false).
*
* Params:
* p = A pointer to the memory block.
@@ -60,7 +63,7 @@ interface Allocator
*
* Returns: $(D_KEYWORD true) if successful, $(D_KEYWORD false) otherwise.
*/
- bool expand(ref void[] p, in size_t size) shared nothrow @nogc;
+ bool reallocateInPlace(ref void[] p, in size_t size) shared nothrow @nogc;
}
/**
diff --git a/source/tanya/memory/mmappool.d b/source/tanya/memory/mmappool.d
index 2bc3cfe..d7a2e5e 100644
--- a/source/tanya/memory/mmappool.d
+++ b/source/tanya/memory/mmappool.d
@@ -231,7 +231,10 @@ final class MmapPool : Allocator
}
/**
- * Expands a memory block in place.
+ * Reallocates a memory block in place if possible or returns
+ * $(D_KEYWORD false). This function cannot be used to allocate or
+ * deallocate memory, so if $(D_PARAM p) is $(D_KEYWORD null) or
+ * $(D_PARAM size) is `0`, it should return $(D_KEYWORD false).
*
* Params:
* p = A pointer to the memory block.
@@ -239,15 +242,17 @@ final class MmapPool : Allocator
*
* Returns: $(D_KEYWORD true) if successful, $(D_KEYWORD false) otherwise.
*/
- bool expand(ref void[] p, in size_t size) shared nothrow @nogc
+ bool reallocateInPlace(ref void[] p, in size_t size) shared nothrow @nogc
{
- if (size <= p.length)
+ if (p is null || size == 0)
{
- return true;
+ return false;
}
- if (p is null)
+ if (size <= p.length)
{
- return false;
+ // Leave the block as is.
+ p = p.ptr[0 .. size];
+ return true;
}
Block block1 = cast(Block) (p.ptr - BlockEntry.sizeof);
@@ -298,22 +303,22 @@ final class MmapPool : Allocator
nothrow unittest
{
void[] p;
- assert(!MmapPool.instance.expand(p, 5));
+ assert(!MmapPool.instance.reallocateInPlace(p, 5));
assert(p is null);
p = MmapPool.instance.allocate(1);
auto orig = p.ptr;
- assert(MmapPool.instance.expand(p, 2));
+ assert(MmapPool.instance.reallocateInPlace(p, 2));
assert(p.length == 2);
assert(p.ptr == orig);
- assert(MmapPool.instance.expand(p, 4));
+ assert(MmapPool.instance.reallocateInPlace(p, 4));
assert(p.length == 4);
assert(p.ptr == orig);
- assert(MmapPool.instance.expand(p, 2));
- assert(p.length == 4);
+ assert(MmapPool.instance.reallocateInPlace(p, 2));
+ assert(p.length == 2);
assert(p.ptr == orig);
MmapPool.instance.deallocate(p);
@@ -339,17 +344,12 @@ final class MmapPool : Allocator
}
return false;
}
- else if (size <= p.length)
- {
- // Leave the block as is.
- p = p.ptr[0 .. size];
- return true;
- }
- else if (expand(p, size))
+ else if (reallocateInPlace(p, size))
{
return true;
}
- // Can't extend, allocate a new block, copy and delete the previous.
+ // Can't reallocate in place, allocate a new block,
+ // copy and delete the previous one.
void[] reallocP = allocate(size);
if (reallocP is null)
{
@@ -587,7 +587,7 @@ final class MmapPool : Allocator
}
// A lot of allocations/deallocations, but it is the minimum caused a
-// segmentation fault because MmapPool expand moves a block wrong.
+// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
unittest
{
auto a = MmapPool.instance.allocate(16);
@@ -602,7 +602,7 @@ unittest
MmapPool.instance.deallocate(c);
a = MmapPool.instance.allocate(50);
- MmapPool.instance.expand(a, 64);
+ MmapPool.instance.reallocateInPlace(a, 64);
MmapPool.instance.deallocate(a);
a = MmapPool.instance.allocate(1);