diff --git a/README.md b/README.md index 93fadf1..e22215c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,6 @@ string, Set, Hash table. * `conv`: This module provides functions for converting between different types. * `encoding`: This package provides tools to work with text encodings. -* `exception`: Common exceptions and errors. * `format`: Formatting and conversion functions. * `functional`: Functions that manipulate other functions and their argument lists. diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d index 2b7a2b8..2b3adfa 100644 --- a/source/tanya/container/array.d +++ b/source/tanya/container/array.d @@ -5,7 +5,7 @@ /** * Single-dimensioned array. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) @@ -17,7 +17,6 @@ module tanya.container.array; import core.checkedint; import tanya.algorithm.comparison; import tanya.algorithm.mutation; -import tanya.exception; import tanya.functional; import tanya.memory; import tanya.meta.trait; diff --git a/source/tanya/container/buffer.d b/source/tanya/container/buffer.d index 4866ca7..b2eeb74 100644 --- a/source/tanya/container/buffer.d +++ b/source/tanya/container/buffer.d @@ -5,7 +5,7 @@ /** * This module contains buffers designed for C-style input/output APIs. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/container/entry.d b/source/tanya/container/entry.d index e976cc3..1e7e28f 100644 --- a/source/tanya/container/entry.d +++ b/source/tanya/container/entry.d @@ -5,7 +5,7 @@ /* * Internal package used by containers that rely on entries/nodes. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/container/hashtable.d b/source/tanya/container/hashtable.d index b80d220..3571f63 100644 --- a/source/tanya/container/hashtable.d +++ b/source/tanya/container/hashtable.d @@ -5,7 +5,7 @@ /** * Hash table. * - * Copyright: Eugene Wissner 2018. + * Copyright: Eugene Wissner 2018-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d index 39edf06..09a5c9f 100644 --- a/source/tanya/container/list.d +++ b/source/tanya/container/list.d @@ -6,7 +6,7 @@ * This module contains singly-linked ($(D_PSYMBOL SList)) and doubly-linked * ($(D_PSYMBOL DList)) lists. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/container/package.d b/source/tanya/container/package.d index 783c5d0..1919b39 100644 --- a/source/tanya/container/package.d +++ b/source/tanya/container/package.d @@ -5,7 +5,7 @@ /** * Abstract data types whose instances are collections of other objects. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/container/set.d b/source/tanya/container/set.d index b95950b..b06ef91 100644 --- a/source/tanya/container/set.d +++ b/source/tanya/container/set.d @@ -6,7 +6,7 @@ * This module implements a $(D_PSYMBOL Set) container that stores unique * values without any particular order. * - * Copyright: Eugene Wissner 2017-2018. + * Copyright: Eugene Wissner 2017-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d index abe60e1..2a50dc6 100644 --- a/source/tanya/container/string.d +++ b/source/tanya/container/string.d @@ -17,7 +17,7 @@ * Internally $(D_PSYMBOL String) is represented by a sequence of * $(D_KEYWORD char)s. * - * Copyright: Eugene Wissner 2017-2018. + * Copyright: Eugene Wissner 2017-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/exception.d b/source/tanya/exception.d index 936e4a7..49a2d40 100644 --- a/source/tanya/exception.d +++ b/source/tanya/exception.d @@ -2,65 +2,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/** - * Common exceptions and errors. - * - * Copyright: Eugene Wissner 2017-2018. +/* + * Copyright: Eugene Wissner 2017-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/exception.d, * tanya/exception.d) */ +deprecated("Use tanya.memory.lifecycle instead") module tanya.exception; -import tanya.conv; -import tanya.memory; - -/** - * Error thrown if memory allocation fails. - */ -final class OutOfMemoryError : Error -{ - /** - * Constructs new error. - * - * Params: - * msg = The message for the exception. - * file = The file where the exception occurred. - * line = The line number where the exception occurred. - * next = The previous exception in the chain of exceptions, if any. - */ - this(string msg = "Out of memory", - string file = __FILE__, - size_t line = __LINE__, - Throwable next = null) @nogc nothrow pure @safe - { - super(msg, file, line, next); - } - - /// ditto - this(string msg, - Throwable next, - string file = __FILE__, - size_t line = __LINE__) @nogc nothrow pure @safe - { - super(msg, file, line, next); - } -} - -/** - * Allocates $(D_PSYMBOL OutOfMemoryError) in a static storage and throws it. - * - * Params: - * msg = Custom error message. - * - * Throws: $(D_PSYMBOL OutOfMemoryError). - */ -void onOutOfMemoryError(string msg = "Out of memory") -@nogc nothrow pure @trusted -{ - static ubyte[stateSize!OutOfMemoryError] memory; - alias PureType = OutOfMemoryError function(string) @nogc nothrow pure; - throw (cast(PureType) () => emplace!OutOfMemoryError(memory))(msg); -} +public import tanya.memory.lifecycle : onOutOfMemoryError, OutOfMemoryError; diff --git a/source/tanya/memory/allocator.d b/source/tanya/memory/allocator.d index 1d8139d..3d05a37 100644 --- a/source/tanya/memory/allocator.d +++ b/source/tanya/memory/allocator.d @@ -8,7 +8,7 @@ * Allocators are classes encapsulating memory allocation strategy. This allows * to decouple memory management from the algorithms and the data. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/memory/lifecycle.d b/source/tanya/memory/lifecycle.d new file mode 100644 index 0000000..2221af3 --- /dev/null +++ b/source/tanya/memory/lifecycle.d @@ -0,0 +1,360 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Lifecycle management functions, types and related exceptions. + * + * Copyright: Eugene Wissner 2019. + * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, + * Mozilla Public License, v. 2.0). + * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) + * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/memory/init.d, + * tanya/memory/init.d) + */ +module tanya.memory.lifecycle; + +import tanya.algorithm.mutation; +import tanya.conv; +import tanya.memory; +import tanya.meta.trait; +import tanya.range.primitive; + +/** + * Error thrown if memory allocation fails. + */ +final class OutOfMemoryError : Error +{ + /** + * Constructs new error. + * + * Params: + * msg = The message for the exception. + * file = The file where the exception occurred. + * line = The line number where the exception occurred. + * next = The previous exception in the chain of exceptions, if any. + */ + this(string msg = "Out of memory", + string file = __FILE__, + size_t line = __LINE__, + Throwable next = null) @nogc nothrow pure @safe + { + super(msg, file, line, next); + } + + /// ditto + this(string msg, + Throwable next, + string file = __FILE__, + size_t line = __LINE__) @nogc nothrow pure @safe + { + super(msg, file, line, next); + } +} + +/** + * Allocates $(D_PSYMBOL OutOfMemoryError) in a static storage and throws it. + * + * Params: + * msg = Custom error message. + * + * Throws: $(D_PSYMBOL OutOfMemoryError). + */ +void onOutOfMemoryError(string msg = "Out of memory") +@nogc nothrow pure @trusted +{ + static ubyte[stateSize!OutOfMemoryError] memory; + alias PureType = OutOfMemoryError function(string) @nogc nothrow pure; + throw (cast(PureType) () => emplace!OutOfMemoryError(memory))(msg); +} + +// From druntime +extern (C) +private void _d_monitordelete(Object h, bool det) @nogc nothrow pure; + +/* + * Internal function used to create, resize or destroy a dynamic array. It + * 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. + * allocator = The allocator used for getting memory. + * array = A reference to the array being changed. + * length = New array length. + * + * Returns: $(D_PARAM array). + */ +package(tanya) T[] resize(T)(shared Allocator allocator, + auto ref T[] array, + const size_t length) @trusted +{ + if (length == 0) + { + if (allocator.deallocate(array)) + { + return null; + } + else + { + onOutOfMemoryError(); + } + } + + void[] buf = array; + if (!allocator.reallocate(buf, length * T.sizeof)) + { + onOutOfMemoryError(); + } + // Casting from void[] is unsafe, but we know we cast to the original type. + array = cast(T[]) buf; + + return array; +} + +@nogc nothrow pure @safe unittest +{ + int[] p; + + p = defaultAllocator.resize(p, 20); + assert(p.length == 20); + + p = defaultAllocator.resize(p, 30); + assert(p.length == 30); + + p = defaultAllocator.resize(p, 10); + assert(p.length == 10); + + p = defaultAllocator.resize(p, 0); + assert(p is null); +} + +/* + * Destroys the object. + * Returns the memory should be freed. + */ +package(tanya) void[] finalize(T)(ref T* p) +{ + if (p is null) + { + return null; + } + static if (hasElaborateDestructor!T) + { + destroy(*p); + } + return (cast(void*) p)[0 .. T.sizeof]; +} + +package(tanya) void[] finalize(T)(ref T p) +if (isPolymorphicType!T) +{ + if (p is null) + { + return null; + } + 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]; + + auto ppv = cast(void**) ptr; + if (!*ppv) + { + return null; + } + 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) + { + alias DtorType = void function(Object) pure nothrow @safe @nogc; + (cast(DtorType) c.destructor)(ob); + } + } + while ((c = c.base) !is null); + + if (ppv[1]) // if monitor is not null + { + _d_monitordelete(cast(Object) ptr, true); + } + return support; +} + +package(tanya) void[] finalize(T)(ref T[] p) +{ + destroyAll(p); + return p; +} + +/** + * Destroys and deallocates $(D_PARAM p) of type $(D_PARAM T). + * It is assumed the respective entities had been allocated with the same + * allocator. + * + * Params: + * 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) +{ + () @trusted { allocator.deallocate(finalize(p)); }(); + p = null; +} + +@nogc nothrow pure @system unittest +{ + static struct S + { + ~this() @nogc nothrow pure @safe + { + } + } + auto p = cast(S[]) defaultAllocator.allocate(S.sizeof); + + defaultAllocator.dispose(p); +} + +// Works with interfaces. +@nogc nothrow pure @safe unittest +{ + interface I + { + } + class C : I + { + } + auto c = defaultAllocator.make!C(); + I i = c; + + defaultAllocator.dispose(i); + defaultAllocator.dispose(i); +} + +/** + * Constructs a new class instance of type $(D_PARAM T) using $(D_PARAM args) + * as the parameter list for the constructor of $(D_PARAM T). + * + * Params: + * T = Class type. + * A = Types of the arguments to the constructor of $(D_PARAM T). + * allocator = Allocator. + * args = Constructor arguments of $(D_PARAM T). + * + * Returns: Newly created $(D_PSYMBOL T). + * + * Precondition: $(D_INLINECODE allocator !is null) + */ +T make(T, A...)(shared Allocator allocator, auto ref A args) +if (is(T == class)) +in (allocator !is null) +{ + auto mem = (() @trusted => allocator.allocate(stateSize!T))(); + if (mem is null) + { + onOutOfMemoryError(); + } + scope (failure) + { + () @trusted { allocator.deallocate(mem); }(); + } + + return emplace!T(mem[0 .. stateSize!T], args); +} + +/** + * Constructs a value object of type $(D_PARAM T) using $(D_PARAM args) + * as the parameter list for the constructor of $(D_PARAM T) and returns a + * pointer to the new object. + * + * Params: + * T = Object type. + * A = Types of the arguments to the constructor of $(D_PARAM T). + * allocator = Allocator. + * args = Constructor arguments of $(D_PARAM T). + * + * Returns: Pointer to the created object. + * + * Precondition: $(D_INLINECODE allocator !is null) + */ +T* make(T, A...)(shared Allocator allocator, auto ref A args) +if (!is(T == interface) + && !is(T == class) + && !isAssociativeArray!T + && !isArray!T) +in (allocator !is null) +{ + auto mem = (() @trusted => allocator.allocate(stateSize!T))(); + if (mem is null) + { + onOutOfMemoryError(); + } + scope (failure) + { + () @trusted { allocator.deallocate(mem); }(); + } + return emplace!T(mem[0 .. stateSize!T], args); +} + +/// +@nogc nothrow pure @safe unittest +{ + int* i = defaultAllocator.make!int(5); + assert(*i == 5); + defaultAllocator.dispose(i); +} + +/** + * Constructs a new array with $(D_PARAM n) elements. + * + * Params: + * T = Array type. + * allocator = Allocator. + * n = Array size. + * + * Returns: Newly created array. + * + * Precondition: $(D_INLINECODE allocator !is null + * && n <= size_t.max / ElementType!T.sizeof) + */ +T make(T)(shared Allocator allocator, const size_t n) +if (isArray!T) +in (allocator !is null) +in (n <= size_t.max / ElementType!T.sizeof) +{ + auto ret = allocator.resize!(ElementType!T)(null, n); + ret.uninitializedFill(ElementType!T.init); + return ret; +} + +/// +@nogc nothrow pure @safe unittest +{ + int[] i = defaultAllocator.make!(int[])(2); + assert(i.length == 2); + assert(i[0] == int.init && i[1] == int.init); + defaultAllocator.dispose(i); +} diff --git a/source/tanya/memory/mallocator.d b/source/tanya/memory/mallocator.d index f7379e8..fdf7ede 100644 --- a/source/tanya/memory/mallocator.d +++ b/source/tanya/memory/mallocator.d @@ -3,9 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Allocator based on $(D_PSYMBOL malloc), $(D_PSYMBOL realloc) and $(D_PSYMBOL free). + * Allocator based on $(D_PSYMBOL malloc), $(D_PSYMBOL realloc) and + * $(D_PSYMBOL free). * - * Copyright: Eugene Wissner 2017-2018. + * Copyright: Eugene Wissner 2017-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/memory/mmappool.d b/source/tanya/memory/mmappool.d index fb3ef06..5c42241 100644 --- a/source/tanya/memory/mmappool.d +++ b/source/tanya/memory/mmappool.d @@ -5,7 +5,7 @@ /* * Native allocator. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) @@ -17,7 +17,6 @@ module tanya.memory.mmappool; version (TanyaNative): import mir.linux._asm.unistd; -import tanya.algorithm.comparison; import tanya.memory.allocator; import tanya.memory.op; import tanya.os.error; diff --git a/source/tanya/memory/op.d b/source/tanya/memory/op.d index 6df7dd3..6005329 100644 --- a/source/tanya/memory/op.d +++ b/source/tanya/memory/op.d @@ -5,7 +5,7 @@ /** * Set of operations on memory blocks. * - * Copyright: Eugene Wissner 2017-2018. + * Copyright: Eugene Wissner 2017-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d index 77dc388..8526b5a 100644 --- a/source/tanya/memory/package.d +++ b/source/tanya/memory/package.d @@ -5,7 +5,7 @@ /** * Dynamic memory management. * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) @@ -14,12 +14,10 @@ */ module tanya.memory; -import tanya.algorithm.mutation; import tanya.conv; -import tanya.exception; public import tanya.memory.allocator; +public import tanya.memory.lifecycle; import tanya.meta.trait; -import tanya.range.primitive; /** * The mixin generates common methods for classes and structs using @@ -86,10 +84,6 @@ mixin template DefaultAllocator() } } -// From druntime -extern (C) -private void _d_monitordelete(Object h, bool det) @nogc nothrow pure; - shared Allocator allocator; private shared(Allocator) getAllocatorInstance() @nogc nothrow @@ -207,302 +201,3 @@ pure nothrow @safe @nogc { return (size - 1) / alignment * alignment + alignment; } - -/* - * Internal function used to create, resize or destroy a dynamic array. It - * 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. - * allocator = The allocator used for getting memory. - * array = A reference to the array being changed. - * length = New array length. - * - * Returns: $(D_PARAM array). - */ -package(tanya) T[] resize(T)(shared Allocator allocator, - auto ref T[] array, - const size_t length) @trusted -{ - if (length == 0) - { - if (allocator.deallocate(array)) - { - return null; - } - else - { - onOutOfMemoryError(); - } - } - - void[] buf = array; - if (!allocator.reallocate(buf, length * T.sizeof)) - { - onOutOfMemoryError(); - } - // Casting from void[] is unsafe, but we know we cast to the original type. - array = cast(T[]) buf; - - return array; -} - -@nogc nothrow pure @safe unittest -{ - int[] p; - - p = defaultAllocator.resize(p, 20); - assert(p.length == 20); - - p = defaultAllocator.resize(p, 30); - assert(p.length == 30); - - p = defaultAllocator.resize(p, 10); - assert(p.length == 10); - - p = defaultAllocator.resize(p, 0); - assert(p is null); -} - -/* - * Destroys the object. - * Returns the memory should be freed. - */ -package(tanya) void[] finalize(T)(ref T* p) -{ - if (p is null) - { - return null; - } - static if (hasElaborateDestructor!T) - { - destroy(*p); - } - return (cast(void*) p)[0 .. T.sizeof]; -} - -package(tanya) void[] finalize(T)(ref T p) -if (isPolymorphicType!T) -{ - if (p is null) - { - return null; - } - 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]; - - auto ppv = cast(void**) ptr; - if (!*ppv) - { - return null; - } - 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) - { - alias DtorType = void function(Object) pure nothrow @safe @nogc; - (cast(DtorType) c.destructor)(ob); - } - } - while ((c = c.base) !is null); - - if (ppv[1]) // if monitor is not null - { - _d_monitordelete(cast(Object) ptr, true); - } - return support; -} - -package(tanya) void[] finalize(T)(ref T[] p) -{ - destroyAll(p); - return p; -} - -/** - * Destroys and deallocates $(D_PARAM p) of type $(D_PARAM T). - * It is assumed the respective entities had been allocated with the same - * allocator. - * - * Params: - * 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) -{ - () @trusted { allocator.deallocate(finalize(p)); }(); - p = null; -} - -@nogc nothrow pure @system unittest -{ - static struct S - { - ~this() @nogc nothrow pure @safe - { - } - } - auto p = cast(S[]) defaultAllocator.allocate(S.sizeof); - - defaultAllocator.dispose(p); -} - -// Works with interfaces. -@nogc nothrow pure @safe unittest -{ - interface I - { - } - class C : I - { - } - auto c = defaultAllocator.make!C(); - I i = c; - - defaultAllocator.dispose(i); - defaultAllocator.dispose(i); -} - -/** - * Constructs a new class instance of type $(D_PARAM T) using $(D_PARAM args) - * as the parameter list for the constructor of $(D_PARAM T). - * - * Params: - * T = Class type. - * A = Types of the arguments to the constructor of $(D_PARAM T). - * allocator = Allocator. - * args = Constructor arguments of $(D_PARAM T). - * - * Returns: Newly created $(D_PSYMBOL T). - * - * Precondition: $(D_INLINECODE allocator !is null) - */ -T make(T, A...)(shared Allocator allocator, auto ref A args) -if (is(T == class)) -in -{ - assert(allocator !is null); -} -do -{ - auto mem = (() @trusted => allocator.allocate(stateSize!T))(); - if (mem is null) - { - onOutOfMemoryError(); - } - scope (failure) - { - () @trusted { allocator.deallocate(mem); }(); - } - - return emplace!T(mem[0 .. stateSize!T], args); -} - -/** - * Constructs a value object of type $(D_PARAM T) using $(D_PARAM args) - * as the parameter list for the constructor of $(D_PARAM T) and returns a - * pointer to the new object. - * - * Params: - * T = Object type. - * A = Types of the arguments to the constructor of $(D_PARAM T). - * allocator = Allocator. - * args = Constructor arguments of $(D_PARAM T). - * - * Returns: Pointer to the created object. - * - * Precondition: $(D_INLINECODE allocator !is null) - */ -T* make(T, A...)(shared Allocator allocator, auto ref A args) -if (!is(T == interface) - && !is(T == class) - && !isAssociativeArray!T - && !isArray!T) -in -{ - assert(allocator !is null); -} -do -{ - auto mem = (() @trusted => allocator.allocate(stateSize!T))(); - if (mem is null) - { - onOutOfMemoryError(); - } - scope (failure) - { - () @trusted { allocator.deallocate(mem); }(); - } - return emplace!T(mem[0 .. stateSize!T], args); -} - -/// -@nogc nothrow pure @safe unittest -{ - int* i = defaultAllocator.make!int(5); - assert(*i == 5); - defaultAllocator.dispose(i); -} - -/** - * Constructs a new array with $(D_PARAM n) elements. - * - * Params: - * T = Array type. - * allocator = Allocator. - * n = Array size. - * - * Returns: Newly created array. - * - * Precondition: $(D_INLINECODE allocator !is null - * && n <= size_t.max / ElementType!T.sizeof) - */ -T make(T)(shared Allocator allocator, const size_t n) -if (isArray!T) -in -{ - assert(allocator !is null); - assert(n <= size_t.max / ElementType!T.sizeof); -} -do -{ - auto ret = allocator.resize!(ElementType!T)(null, n); - ret.uninitializedFill(ElementType!T.init); - return ret; -} - -/// -@nogc nothrow pure @safe unittest -{ - int[] i = defaultAllocator.make!(int[])(2); - assert(i.length == 2); - assert(i[0] == int.init && i[1] == int.init); - defaultAllocator.dispose(i); -} diff --git a/source/tanya/memory/smartref.d b/source/tanya/memory/smartref.d index 020627d..90271e7 100644 --- a/source/tanya/memory/smartref.d +++ b/source/tanya/memory/smartref.d @@ -14,7 +14,7 @@ * $(LI Unique ownership) * ) * - * Copyright: Eugene Wissner 2016-2018. + * Copyright: Eugene Wissner 2016-2019. * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * Mozilla Public License, v. 2.0). * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) @@ -23,10 +23,8 @@ */ module tanya.memory.smartref; -import tanya.algorithm.comparison; import tanya.algorithm.mutation; import tanya.conv; -import tanya.exception; import tanya.memory; import tanya.meta.trait; import tanya.range.primitive;