Add capacity capabilities to the vector

This commit is contained in:
2016-12-18 18:48:25 +01:00
parent c1fb89af99
commit 40857e69b7
11 changed files with 500 additions and 341 deletions

View File

@ -28,7 +28,7 @@ interface Allocator
*
* Returns: Pointer to the new allocated memory.
*/
void[] allocate(size_t size) shared nothrow @safe @nogc;
void[] allocate(size_t size) shared nothrow @nogc;
/**
* Deallocates a memory block.
@ -38,7 +38,7 @@ interface Allocator
*
* Returns: Whether the deallocation was successful.
*/
bool deallocate(void[] p) shared nothrow @safe @nogc;
bool deallocate(void[] p) shared nothrow @nogc;
/**
* Increases or decreases the size of a memory block.
@ -49,5 +49,32 @@ interface Allocator
*
* Returns: Pointer to the allocated memory.
*/
bool reallocate(ref void[] p, size_t size) shared nothrow @safe @nogc;
bool reallocate(ref void[] p, size_t size) shared nothrow @nogc;
}
/**
* The mixin generates common methods for classes and structs using
* allocators. It provides a protected member and a read-only property,
* that checks if an allocator was already set and sets it to the default
* one, if not (useful for structs which don't have a default constructor).
*/
mixin template DefaultAllocator()
{
/// Allocator.
protected shared Allocator allocator_;
/**
* This property checks if the allocator was set in the constructor
* and sets it to the default one, if not.
*
* Returns: Used allocator.
*/
@property shared(Allocator) allocator() nothrow @safe @nogc
{
if (allocator_ is null)
{
allocator_ = defaultAllocator;
}
return allocator_;
}
}

View File

@ -73,7 +73,7 @@ final class MmapPool : Allocator
*
* Returns: Pointer to the new allocated memory.
*/
void[] allocate(size_t size) shared nothrow @trusted
void[] allocate(size_t size) shared nothrow
{
if (!size)
{
@ -91,7 +91,7 @@ final class MmapPool : Allocator
}
///
@safe nothrow unittest
nothrow unittest
{
auto p = MmapPool.instance.allocate(20);
@ -167,7 +167,7 @@ final class MmapPool : Allocator
*
* Returns: Whether the deallocation was successful.
*/
bool deallocate(void[] p) shared nothrow @trusted
bool deallocate(void[] p) shared nothrow
{
if (p is null)
{
@ -207,7 +207,7 @@ final class MmapPool : Allocator
}
///
@safe nothrow unittest
nothrow unittest
{
auto p = MmapPool.instance.allocate(20);
@ -223,7 +223,7 @@ final class MmapPool : Allocator
*
* Returns: Whether the reallocation was successful.
*/
bool reallocate(ref void[] p, size_t size) shared nothrow @trusted
bool reallocate(ref void[] p, size_t size) shared nothrow
{
void[] reallocP;
@ -291,7 +291,7 @@ final class MmapPool : Allocator
*
* Returns: Global $(D_PSYMBOL MmapPool) instance.
*/
static @property ref shared(MmapPool) instance() nothrow @trusted
static @property ref shared(MmapPool) instance() nothrow
{
if (instance_ is null)
{
@ -310,7 +310,7 @@ final class MmapPool : Allocator
}
///
@safe nothrow unittest
nothrow unittest
{
assert(instance is instance);
}

View File

@ -20,7 +20,7 @@ private extern (C) void _d_monitordelete(Object h, bool det) nothrow @nogc;
shared Allocator allocator;
shared static this() nothrow @safe @nogc
shared static this() nothrow @trusted @nogc
{
import tanya.memory.mmappool;
allocator = MmapPool.instance;
@ -75,17 +75,20 @@ bool resizeArray(T)(shared Allocator allocator,
void[] buf = array;
immutable oldLength = array.length;
if (!allocator.reallocate(buf, length * T.sizeof))
{
return false;
}
// Casting from void[] is unsafe, but we know we cast to the original type
array = () @trusted { return cast(T[]) buf; }();
if (oldLength < length)
auto result = () @trusted {
if (!allocator.reallocate(buf, length * T.sizeof))
{
return false;
}
// Casting from void[] is unsafe, but we know we cast to the original type.
array = cast(T[]) buf;
return true;
}();
if (result && oldLength < length)
{
array[oldLength .. $] = init;
}
return true;
return result;
}
///
@ -106,26 +109,6 @@ unittest
assert(p is null);
}
private void deStruct(T)(ref T s)
if (is(T == struct))
{
static if (__traits(hasMember, T, "__xdtor")
&& __traits(isSame, T, __traits(parent, s.__xdtor)))
{
s.__xdtor();
}
auto buf = (cast(ubyte*) &s)[0 .. T.sizeof];
auto init = cast(ubyte[])typeid(T).initializer();
if (init.ptr is null) // null ptr means initialize to 0s
{
buf[] = 0;
}
else
{
buf[] = init[];
}
}
/**
* Destroys and deallocates $(D_PARAM p) of type $(D_PARAM T).
* It is assumed the respective entities had been allocated with the same
@ -136,17 +119,18 @@ private void deStruct(T)(ref T s)
* allocator = Allocator the $(D_PARAM p) was allocated with.
* p = Object or array to be destroyed.
*/
void dispose(T)(shared Allocator allocator, T* p)
void dispose(T)(shared Allocator allocator, auto ref T* p)
{
static if (hasElaborateDestructor!T)
{
deStruct(*p);
}
allocator.deallocate((cast(void*) p)[0 .. T.sizeof]);
static if (hasElaborateDestructor!T)
{
destroy(*p);
}
() @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }();
p = null;
}
/// Ditto.
void dispose(T)(shared Allocator allocator, T p)
void dispose(T)(shared Allocator allocator, auto ref T p)
if (is(T == class) || is(T == interface))
{
if (p is null)
@ -172,7 +156,8 @@ void dispose(T)(shared Allocator allocator, T p)
auto support = ptr[0 .. typeid(ob).initializer.length];
scope (success)
{
allocator.deallocate(support);
() @trusted { allocator.deallocate(support); }();
p = null;
}
auto ppv = cast(void**) ptr;
@ -193,7 +178,7 @@ void dispose(T)(shared Allocator allocator, T p)
// shouldn't throw and if it does, it is an error anyway.
if (c.destructor)
{
(cast(void function (Object) nothrow @nogc) c.destructor)(ob);
(cast(void function (Object) nothrow @safe @nogc) c.destructor)(ob);
}
}
while ((c = c.base) !is null);
@ -202,19 +187,18 @@ void dispose(T)(shared Allocator allocator, T p)
{
_d_monitordelete(cast(Object) ptr, true);
}
auto w = (*pc).initializer;
ptr[0 .. w.length] = w[];
}
/// Ditto.
void dispose(T)(shared Allocator allocator, T[] array)
void dispose(T)(shared Allocator allocator, auto ref T[] array)
{
static if (hasElaborateDestructor!(typeof(array[0])))
{
foreach (ref e; array)
{
deStruct(e);
}
}
allocator.deallocate(array);
static if (hasElaborateDestructor!(typeof(array[0])))
{
foreach (ref e; array)
{
destroy(e);
}
}
() @trusted { allocator.deallocate(array); }();
array = null;
}