Add capacity capabilities to the vector
This commit is contained in:
@ -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_;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user