diff options
Diffstat (limited to 'source/tanya/memory/package.d')
| -rw-r--r-- | source/tanya/memory/package.d | 389 |
1 files changed, 190 insertions, 199 deletions
diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d index 9ecb45b..5e05943 100644 --- a/source/tanya/memory/package.d +++ b/source/tanya/memory/package.d @@ -11,7 +11,7 @@ module tanya.memory; import core.exception; -public import std.experimental.allocator : make, makeArray; +public import std.experimental.allocator : make; import std.traits; public import tanya.memory.allocator; @@ -23,59 +23,61 @@ public import tanya.memory.allocator; */ mixin template DefaultAllocator() { - /// Allocator. - protected shared Allocator allocator_; + /// Allocator. + protected shared Allocator allocator_; - /** - * Params: - * allocator = The allocator should be used. - */ - this(shared Allocator allocator) - in - { - assert(allocator !is null); - } - body - { - this.allocator_ = allocator; - } + /** + * Params: + * allocator = The allocator should be used. + * + * Precondition: $(D_INLINECODE allocator_ !is null) + */ + this(shared Allocator allocator) + in + { + assert(allocator !is null); + } + body + { + this.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. - * - * Postcondition: $(D_INLINECODE allocator_ !is null) - */ - protected @property shared(Allocator) allocator() nothrow @safe @nogc - out (allocator) - { - assert(allocator !is null); - } - body - { - if (allocator_ is null) - { - allocator_ = defaultAllocator; - } - return allocator_; - } + /** + * This property checks if the allocator was set in the constructor + * and sets it to the default one, if not. + * + * Returns: Used allocator. + * + * Postcondition: $(D_INLINECODE allocator !is null) + */ + protected @property shared(Allocator) allocator() nothrow @safe @nogc + out (allocator) + { + assert(allocator !is null); + } + body + { + if (allocator_ is null) + { + allocator_ = defaultAllocator; + } + return allocator_; + } - /// Ditto. - @property shared(Allocator) allocator() const nothrow @trusted @nogc - out (allocator) - { - assert(allocator !is null); - } - body - { - if (allocator_ is null) - { - return defaultAllocator; - } - return cast(shared Allocator) allocator_; - } + /// Ditto. + @property shared(Allocator) allocator() const nothrow @trusted @nogc + out (allocator) + { + assert(allocator !is null); + } + body + { + if (allocator_ is null) + { + return defaultAllocator; + } + return cast(shared Allocator) allocator_; + } } // From druntime @@ -85,28 +87,28 @@ shared Allocator allocator; shared static this() nothrow @trusted @nogc { - import tanya.memory.mmappool; - allocator = MmapPool.instance; + import tanya.memory.mallocator; + allocator = Mallocator.instance; } @property ref shared(Allocator) defaultAllocator() nothrow @safe @nogc out (allocator) { - assert(allocator !is null); + assert(allocator !is null); } body { - return allocator; + return allocator; } @property void defaultAllocator(shared(Allocator) allocator) nothrow @safe @nogc in { - assert(allocator !is null); + assert(allocator !is null); } body { - .allocator = allocator; + .allocator = allocator; } /** @@ -114,101 +116,90 @@ body * object of type $(D_PARAM T). * * Params: - * T = Object type. + * T = Object type. */ template stateSize(T) { - static if (is(T == class) || is(T == interface)) - { - enum stateSize = __traits(classInstanceSize, T); - } - else - { - enum stateSize = T.sizeof; - } + static if (is(T == class) || is(T == interface)) + { + enum stateSize = __traits(classInstanceSize, T); + } + else + { + enum stateSize = T.sizeof; + } } /** * Params: - * size = Raw size. - * alignment = Alignment. + * size = Raw size. + * alignment = Alignment. * * Returns: Aligned size. */ -size_t alignedSize(in size_t size, in size_t alignment = 8) pure nothrow @safe @nogc +size_t alignedSize(const size_t size, const size_t alignment = 8) +pure nothrow @safe @nogc { - return (size - 1) / alignment * alignment + alignment; + return (size - 1) / alignment * alignment + alignment; } /** * Internal function used to create, resize or destroy a dynamic array. It - * throws $(D_PSYMBOL OutOfMemoryError) if $(D_PARAM Throws) is set. The new - * allocated part of the array is initialized only if $(D_PARAM Init) - * is set. This function can be trusted only in the data structures that - * can ensure that the array is allocated/rellocated/deallocated with the - * same allocator. + * may throw $(D_PSYMBOL OutOfMemoryError). The new + * allocated part of the array isn't initialized. This function can be trusted + * only in the data structures that can ensure that the array is + * allocated/rellocated/deallocated with the same allocator. * * Params: - * T = Element type of the array being created. - * Init = If should be initialized. - * Throws = If $(D_PSYMBOL OutOfMemoryError) should be throwsn. - * allocator = The allocator used for getting memory. - * array = A reference to the array being changed. - * length = New array length. + * T = Element type of the array being created. + * allocator = The allocator used for getting memory. + * array = A reference to the array being changed. + * length = New array length. * - * Returns: $(D_KEYWORD true) upon success, $(D_KEYWORD false) if memory could - * not be reallocated. In the latter + * Returns: $(D_PARAM array). */ -package(tanya) bool resize(T, - bool Init = true, - bool Throws = true) - (shared Allocator allocator, - ref T[] array, - in size_t length) @trusted +package(tanya) T[] resize(T)(shared Allocator allocator, + auto ref T[] array, + const size_t length) @trusted { - void[] buf = array; - static if (Init) - { - immutable oldLength = array.length; - } - if (!allocator.reallocate(buf, length * T.sizeof)) - { - static if (Throws) - { - onOutOfMemoryError; - } - return false; - } - // Casting from void[] is unsafe, but we know we cast to the original type. - array = cast(T[]) buf; + if (length == 0) + { + if (allocator.deallocate(array)) + { + return null; + } + else + { + onOutOfMemoryErrorNoGC(); + } + } - static if (Init) - { - if (oldLength < length) - { - array[oldLength .. $] = T.init; - } - } - return true; + void[] buf = array; + if (!allocator.reallocate(buf, length * T.sizeof)) + { + onOutOfMemoryErrorNoGC(); + } + // Casting from void[] is unsafe, but we know we cast to the original type. + array = cast(T[]) buf; + + return array; } -package(tanya) alias resizeArray = resize; -/// -unittest +private unittest { - int[] p; + int[] p; - defaultAllocator.resizeArray(p, 20); - assert(p.length == 20); + p = defaultAllocator.resize(p, 20); + assert(p.length == 20); - defaultAllocator.resizeArray(p, 30); - assert(p.length == 30); + p = defaultAllocator.resize(p, 30); + assert(p.length == 30); - defaultAllocator.resizeArray(p, 10); - assert(p.length == 10); + p = defaultAllocator.resize(p, 10); + assert(p.length == 10); - defaultAllocator.resizeArray(p, 0); - assert(p is null); + p = defaultAllocator.resize(p, 0); + assert(p is null); } /** @@ -217,101 +208,101 @@ unittest * allocator. * * Params: - * T = Type of $(D_PARAM p). - * allocator = Allocator the $(D_PARAM p) was allocated with. - * p = Object or array to be destroyed. + * T = Type of $(D_PARAM p). + * allocator = Allocator the $(D_PARAM p) was allocated with. + * p = Object or array to be destroyed. */ void dispose(T)(shared Allocator allocator, auto ref T* p) { - static if (hasElaborateDestructor!T) - { - destroy(*p); - } - () @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }(); - p = null; + static if (hasElaborateDestructor!T) + { + destroy(*p); + } + () @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }(); + p = null; } /// Ditto. void dispose(T)(shared Allocator allocator, auto ref T p) - if (is(T == class) || is(T == interface)) + if (is(T == class) || is(T == interface)) { - if (p is null) - { - return; - } - static if (is(T == interface)) - { - version(Windows) - { - import core.sys.windows.unknwn : IUnknown; - static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in " - ~ __PRETTY_FUNCTION__); - } - auto ob = cast(Object) p; - } - else - { - alias ob = p; - } - auto ptr = cast(void *) ob; + if (p is null) + { + return; + } + static if (is(T == interface)) + { + version(Windows) + { + import core.sys.windows.unknwn : IUnknown; + static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in " + ~ __PRETTY_FUNCTION__); + } + auto ob = cast(Object) p; + } + else + { + alias ob = p; + } + auto ptr = cast(void *) ob; - auto support = ptr[0 .. typeid(ob).initializer.length]; - scope (success) - { - () @trusted { allocator.deallocate(support); }(); - p = null; - } + auto support = ptr[0 .. typeid(ob).initializer.length]; + scope (success) + { + () @trusted { allocator.deallocate(support); }(); + p = null; + } - auto ppv = cast(void**) ptr; - if (!*ppv) - { - return; - } - auto pc = cast(ClassInfo*) *ppv; - scope (exit) - { - *ppv = null; - } + auto ppv = cast(void**) ptr; + if (!*ppv) + { + return; + } + auto pc = cast(ClassInfo*) *ppv; + scope (exit) + { + *ppv = null; + } - auto c = *pc; - do - { - // Assume the destructor is @nogc. Leave it nothrow since the destructor - // shouldn't throw and if it does, it is an error anyway. - if (c.destructor) - { - (cast(void function (Object) nothrow @safe @nogc) c.destructor)(ob); - } - } - while ((c = c.base) !is null); + auto c = *pc; + do + { + // Assume the destructor is @nogc. Leave it nothrow since the destructor + // shouldn't throw and if it does, it is an error anyway. + if (c.destructor) + { + (cast(void function (Object) nothrow @safe @nogc) c.destructor)(ob); + } + } + while ((c = c.base) !is null); - if (ppv[1]) // if monitor is not null - { - _d_monitordelete(cast(Object) ptr, true); - } + if (ppv[1]) // if monitor is not null + { + _d_monitordelete(cast(Object) ptr, true); + } } /// Ditto. void dispose(T)(shared Allocator allocator, auto ref T[] p) { - static if (hasElaborateDestructor!(typeof(p[0]))) - { - import std.algorithm.iteration; - p.each!(e => destroy(e)); - } - () @trusted { allocator.deallocate(p); }(); - p = null; + static if (hasElaborateDestructor!(typeof(p[0]))) + { + import std.algorithm.iteration; + p.each!(e => destroy(e)); + } + () @trusted { allocator.deallocate(p); }(); + p = null; } unittest { - struct S - { - ~this() - { - } - } - auto p = cast(S[]) defaultAllocator.allocate(S.sizeof); + struct S + { + ~this() + { + } + } + auto p = cast(S[]) defaultAllocator.allocate(S.sizeof); - defaultAllocator.dispose(p); + defaultAllocator.dispose(p); } |
