summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml6
-rw-r--r--appveyor.yml1
-rw-r--r--dub.json6
-rw-r--r--encoding/dub.json9
-rw-r--r--encoding/tanya/encoding/ascii.d (renamed from encoding/source/tanya/encoding/ascii.d)2
-rw-r--r--encoding/tanya/encoding/package.d (renamed from encoding/source/tanya/encoding/package.d)2
-rw-r--r--memory/dub.json18
-rw-r--r--memory/tanya/memory/allocator.d (renamed from source/tanya/memory/allocator.d)2
-rw-r--r--memory/tanya/memory/lifecycle.d984
-rw-r--r--memory/tanya/memory/mallocator.d (renamed from source/tanya/memory/mallocator.d)2
-rw-r--r--memory/tanya/memory/mmappool.d (renamed from source/tanya/memory/mmappool.d)4
-rw-r--r--memory/tanya/memory/op.d (renamed from source/tanya/memory/op.d)2
-rw-r--r--memory/tanya/memory/package.d (renamed from source/tanya/memory/package.d)87
-rw-r--r--memory/tanya/memory/smartref.d (renamed from source/tanya/memory/smartref.d)37
-rw-r--r--memory/tanya/test/assertion.d (renamed from source/tanya/test/assertion.d)0
-rw-r--r--memory/tanya/test/package.d (renamed from source/tanya/test/package.d)0
-rw-r--r--memory/tanya/test/stub.d (renamed from source/tanya/test/stub.d)0
-rw-r--r--meta/dub.json9
-rw-r--r--meta/tanya/meta/metafunction.d (renamed from meta/source/tanya/meta/metafunction.d)4
-rw-r--r--meta/tanya/meta/package.d (renamed from meta/source/tanya/meta/package.d)4
-rw-r--r--meta/tanya/meta/trait.d (renamed from meta/source/tanya/meta/trait.d)56
-rw-r--r--meta/tanya/meta/transform.d (renamed from meta/source/tanya/meta/transform.d)4
-rw-r--r--os/dub.json9
-rw-r--r--os/tanya/os/error.d (renamed from os/source/tanya/os/error.d)2
-rw-r--r--os/tanya/os/package.d (renamed from os/source/tanya/os/package.d)2
-rw-r--r--source/tanya/algorithm/iteration.d2
-rw-r--r--source/tanya/algorithm/mutation.d289
-rw-r--r--source/tanya/container/array.d1
-rw-r--r--source/tanya/container/entry.d2
-rw-r--r--source/tanya/container/list.d1
-rw-r--r--source/tanya/conv.d271
-rw-r--r--source/tanya/functional.d68
-rw-r--r--source/tanya/memory/lifecycle.d360
-rw-r--r--source/tanya/net/ip.d1
-rw-r--r--source/tanya/range/adapter.d2
-rw-r--r--source/tanya/range/primitive.d2
-rw-r--r--source/tanya/typecons.d4
-rw-r--r--sys/dub.json9
-rw-r--r--sys/tanya/sys/linux/syscall.d (renamed from sys/source/tanya/sys/linux/syscall.d)2
-rw-r--r--sys/tanya/sys/posix/ioctl.d (renamed from sys/source/tanya/sys/posix/ioctl.d)2
-rw-r--r--sys/tanya/sys/posix/mman.d (renamed from sys/source/tanya/sys/posix/mman.d)2
-rw-r--r--sys/tanya/sys/posix/net/if_.d (renamed from sys/source/tanya/sys/posix/net/if_.d)2
-rw-r--r--sys/tanya/sys/posix/socket.d (renamed from sys/source/tanya/sys/posix/socket.d)2
-rw-r--r--sys/tanya/sys/windows/def.d (renamed from sys/source/tanya/sys/windows/def.d)2
-rw-r--r--sys/tanya/sys/windows/ifdef.d (renamed from sys/source/tanya/sys/windows/ifdef.d)2
-rw-r--r--sys/tanya/sys/windows/iphlpapi.d (renamed from sys/source/tanya/sys/windows/iphlpapi.d)2
-rw-r--r--sys/tanya/sys/windows/package.d (renamed from sys/source/tanya/sys/windows/package.d)2
-rw-r--r--sys/tanya/sys/windows/winbase.d (renamed from sys/source/tanya/sys/windows/winbase.d)2
-rw-r--r--sys/tanya/sys/windows/winsock2.d (renamed from sys/source/tanya/sys/windows/winsock2.d)2
49 files changed, 1156 insertions, 1130 deletions
diff --git a/.travis.yml b/.travis.yml
index 3cb4f7a..ee8283f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,7 +23,7 @@ matrix:
include:
- name: D-Scanner
d: dmd-$LATEST
- env: DSCANNER=0.6.0
+ env: DSCANNER=0.7.0
os: linux
- name: DDoc
d: dmd-$LATEST
@@ -32,7 +32,7 @@ matrix:
allow_failures:
- name: D-Scanner
d: dmd-$LATEST
- env: DSCANNER=0.6.0
+ env: DSCANNER=0.7.0
os: linux
addons:
@@ -53,12 +53,14 @@ script:
dub build :sys -b ddox --compiler=$DC;
dub build :os -b ddox --compiler=$DC;
dub build :encoding -b ddox --compiler=$DC;
+ dub build :memory -b ddox --compiler=$DC;
dub build -b ddox --compiler=$DC;
elif [ -z "$DSCANNER" ]; then
dub test :meta -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :sys -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :os -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :encoding -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
+ dub test :memory -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
else
dub fetch dscanner --version=$DSCANNER;
diff --git a/appveyor.yml b/appveyor.yml
index fd4db00..dc0e5e8 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -61,4 +61,5 @@ test_script:
- dub test :sys -b unittest --arch=%Darch% --compiler=%DC%
- dub test :os -b unittest --arch=%Darch% --compiler=%DC%
- dub test :encoding -b unittest --arch=%Darch% --compiler=%DC%
+ - dub test :memory -b unittest --arch=%Darch% --compiler=%DC%
- dub test -b unittest --arch=%Darch% --compiler=%DC%
diff --git a/dub.json b/dub.json
index 823f97f..3fd1ec6 100644
--- a/dub.json
+++ b/dub.json
@@ -13,7 +13,8 @@
"tanya:meta": "*",
"tanya:sys": "*",
"tanya:os": "*",
- "tanya:encoding": "*"
+ "tanya:encoding": "*",
+ "tanya:memory": "*"
},
"dependencies-linux": {
@@ -24,7 +25,8 @@
"./meta",
"./sys",
"./os",
- "./encoding"
+ "./encoding",
+ "./memory"
],
"configurations": [
diff --git a/encoding/dub.json b/encoding/dub.json
index 9c50acd..00ef6de 100644
--- a/encoding/dub.json
+++ b/encoding/dub.json
@@ -5,5 +5,12 @@
"dependencies": {
"tanya:meta": "*"
- }
+ },
+
+ "sourcePaths": [
+ "."
+ ],
+ "importPaths": [
+ "."
+ ]
}
diff --git a/encoding/source/tanya/encoding/ascii.d b/encoding/tanya/encoding/ascii.d
index c664861..6498547 100644
--- a/encoding/source/tanya/encoding/ascii.d
+++ b/encoding/tanya/encoding/ascii.d
@@ -12,7 +12,7 @@
* 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/encoding/ascii.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/encoding/tanya/encoding/ascii.d,
* tanya/encoding/ascii.d)
*/
module tanya.encoding.ascii;
diff --git a/encoding/source/tanya/encoding/package.d b/encoding/tanya/encoding/package.d
index e9912ee..9ec74d0 100644
--- a/encoding/source/tanya/encoding/package.d
+++ b/encoding/tanya/encoding/package.d
@@ -9,7 +9,7 @@
* 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/encoding/package.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/encoding/tanya/encoding/package.d,
* tanya/encoding/package.d)
*/
module tanya.encoding;
diff --git a/memory/dub.json b/memory/dub.json
new file mode 100644
index 0000000..7339127
--- /dev/null
+++ b/memory/dub.json
@@ -0,0 +1,18 @@
+{
+ "name": "memory",
+ "description": "Tools for manual memory management (allocators, smart pointers)",
+ "targetType": "library",
+
+ "dependencies": {
+ "tanya:meta": "*",
+ "tanya:os": "*",
+ "tanya:sys": "*"
+ },
+
+ "sourcePaths": [
+ "."
+ ],
+ "importPaths": [
+ "."
+ ]
+}
diff --git a/source/tanya/memory/allocator.d b/memory/tanya/memory/allocator.d
index 3d05a37..e161612 100644
--- a/source/tanya/memory/allocator.d
+++ b/memory/tanya/memory/allocator.d
@@ -12,7 +12,7 @@
* 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/allocator.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/allocator.d,
* tanya/memory/allocator.d)
*/
module tanya.memory.allocator;
diff --git a/memory/tanya/memory/lifecycle.d b/memory/tanya/memory/lifecycle.d
new file mode 100644
index 0000000..35d251b
--- /dev/null
+++ b/memory/tanya/memory/lifecycle.d
@@ -0,0 +1,984 @@
+/* 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/memory/tanya/memory/lifecycle.d,
+ * tanya/memory/lifecycle.d)
+ */
+module tanya.memory.lifecycle;
+
+import tanya.memory : defaultAllocator;
+import tanya.memory.allocator;
+import tanya.meta.trait;
+import tanya.meta.metafunction;
+version (unittest) import tanya.test.stub;
+
+/**
+ * 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.memory) 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.memory) 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.memory) void[] finalize(T)(ref T[] p)
+{
+ destroyAllImpl!(T[], T)(p);
+ return p;
+}
+
+package(tanya) void destroyAllImpl(R, E)(R p)
+{
+ static if (hasElaborateDestructor!E)
+ {
+ foreach (ref e; p)
+ {
+ destroy(e);
+ }
+ }
+}
+
+/**
+ * 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 (!isPolymorphicType!T && !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.
+ * E = Array element type.
+ * allocator = Allocator.
+ * n = Array size.
+ *
+ * Returns: Newly created array.
+ *
+ * Precondition: $(D_INLINECODE allocator !is null
+ * && n <= size_t.max / E.sizeof)
+ */
+T make(T : E[], E)(shared Allocator allocator, size_t n)
+in (allocator !is null)
+in (n <= size_t.max / E.sizeof)
+{
+ auto ret = allocator.resize!E(null, n);
+
+ static if (hasElaborateDestructor!E)
+ {
+ for (auto range = ret; range.length != 0; range = range[1 .. $])
+ {
+ emplace!E(cast(void[]) range[0 .. 1], E.init);
+ }
+ }
+ else
+ {
+ ret[] = E.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);
+}
+
+/**
+ * Constructs a new object of type $(D_PARAM T) in $(D_PARAM memory) with the
+ * given arguments.
+ *
+ * If $(D_PARAM T) is a $(D_KEYWORD class), emplace returns a class reference
+ * of type $(D_PARAM T), otherwise a pointer to the constructed object is
+ * returned.
+ *
+ * If $(D_PARAM T) is a nested class inside another class, $(D_PARAM outer)
+ * should be an instance of the outer class.
+ *
+ * $(D_PARAM args) are arguments for the constructor of $(D_PARAM T). If
+ * $(D_PARAM T) isn't an aggregate type and doesn't have a constructor,
+ * $(D_PARAM memory) can be initialized to `args[0]` if `Args.length == 1`,
+ * `Args[0]` should be implicitly convertible to $(D_PARAM T) then.
+ *
+ * Params:
+ * T = Constructed type.
+ * U = Type of the outer class if $(D_PARAM T) is a nested class.
+ * Args = Types of the constructor arguments if $(D_PARAM T) has a constructor
+ * or the type of the initial value.
+ * outer = Outer class instance if $(D_PARAM T) is a nested class.
+ * args = Constructor arguments if $(D_PARAM T) has a constructor or the
+ * initial value.
+ *
+ * Returns: New instance of type $(D_PARAM T) constructed in $(D_PARAM memory).
+ *
+ * Precondition: `memory.length == stateSize!T`.
+ * Postcondition: $(D_PARAM memory) and the result point to the same memory.
+ */
+T emplace(T, U, Args...)(void[] memory, U outer, auto ref Args args)
+if (!isAbstractClass!T && isInnerClass!T && is(typeof(T.outer) == U))
+in (memory.length >= stateSize!T)
+out (result; memory.ptr is (() @trusted => cast(void*) result)())
+{
+ import tanya.memory.op : copy;
+
+ copy(typeid(T).initializer, memory);
+
+ auto result = (() @trusted => cast(T) memory.ptr)();
+ result.outer = outer;
+
+ static if (is(typeof(result.__ctor(args))))
+ {
+ result.__ctor(args);
+ }
+
+ return result;
+}
+
+/// ditto
+T emplace(T, Args...)(void[] memory, auto ref Args args)
+if (is(T == class) && !isAbstractClass!T && !isInnerClass!T)
+in (memory.length == stateSize!T)
+out (result; memory.ptr is (() @trusted => cast(void*) result)())
+{
+ import tanya.memory.op : copy;
+
+ copy(typeid(T).initializer, memory);
+
+ auto result = (() @trusted => cast(T) memory.ptr)();
+ static if (is(typeof(result.__ctor(args))))
+ {
+ result.__ctor(args);
+ }
+ return result;
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ class C
+ {
+ int i = 5;
+ class Inner
+ {
+ int i;
+
+ this(int param) pure nothrow @safe @nogc
+ {
+ this.i = param;
+ }
+ }
+ }
+ ubyte[stateSize!C] memory1;
+ ubyte[stateSize!(C.Inner)] memory2;
+
+ auto c = emplace!C(memory1);
+ assert(c.i == 5);
+
+ auto inner = emplace!(C.Inner)(memory2, c, 8);
+ assert(c.i == 5);
+ assert(inner.i == 8);
+ assert(inner.outer is c);
+}
+
+/// ditto
+T* emplace(T, Args...)(void[] memory, auto ref Args args)
+if (!isAggregateType!T && (Args.length <= 1))
+in (memory.length >= T.sizeof)
+out (result; memory.ptr is result)
+{
+ auto result = (() @trusted => cast(T*) memory.ptr)();
+ static if (Args.length == 1)
+ {
+ *result = T(args[0]);
+ }
+ else
+ {
+ *result = T.init;
+ }
+ return result;
+}
+
+private void initializeOne(T)(ref void[] memory, ref T* result) @trusted
+{
+ import tanya.memory.op : copy, fill;
+
+ static if (!hasElaborateAssign!T && isAssignable!T)
+ {
+ *result = T.init;
+ }
+ else static if (__VERSION__ >= 2083 // __traits(isZeroInit) available.
+ && __traits(isZeroInit, T))
+ {
+ memory.ptr[0 .. T.sizeof].fill!0;
+ }
+ else
+ {
+ static immutable T init = T.init;
+ copy((&init)[0 .. 1], memory);
+ }
+}
+
+/// ditto
+T* emplace(T, Args...)(void[] memory, auto ref Args args)
+if (!isPolymorphicType!T && isAggregateType!T)
+in (memory.length >= T.sizeof)
+out (result; memory.ptr is result)
+{
+ auto result = (() @trusted => cast(T*) memory.ptr)();
+
+ static if (Args.length == 0)
+ {
+ static assert(is(typeof({ static T t; })),
+ "Default constructor is disabled");
+ initializeOne(memory, result);
+ }
+ else static if (is(typeof(result.__ctor(args))))
+ {
+ initializeOne(memory, result);
+ result.__ctor(args);
+ }
+ else static if (Args.length == 1 && is(typeof({ T t = args[0]; })))
+ {
+ import tanya.memory.op : copy;
+
+ ((ref arg) @trusted =>
+ copy((cast(void*) &arg)[0 .. T.sizeof], memory))(args[0]);
+ static if (hasElaborateCopyConstructor!T)
+ {
+ result.__postblit();
+ }
+ }
+ else static if (is(typeof({ T t = T(args); })))
+ {
+ auto init = T(args);
+ (() @trusted => moveEmplace(init, *result))();
+ }
+ else
+ {
+ static assert(false,
+ "Unable to construct value with the given arguments");
+ }
+ return result;
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ ubyte[4] memory;
+
+ auto i = emplace!int(memory);
+ static assert(is(typeof(i) == int*));
+ assert(*i == 0);
+
+ i = emplace!int(memory, 5);
+ assert(*i == 5);
+
+ static struct S
+ {
+ int i;
+ @disable this();
+ @disable this(this);
+ this(int i) @nogc nothrow pure @safe
+ {
+ this.i = i;
+ }
+ }
+ auto s = emplace!S(memory, 8);
+ static assert(is(typeof(s) == S*));
+ assert(s.i == 8);
+}
+
+// Handles "Cannot access frame pointer" error.
+@nogc nothrow pure @safe unittest
+{
+ struct F
+ {
+ ~this() @nogc nothrow pure @safe
+ {
+ }
+ }
+ static assert(is(typeof(emplace!F((void[]).init))));
+}
+
+// Can emplace structs without a constructor
+@nogc nothrow pure @safe unittest
+{
+ static assert(is(typeof(emplace!WithDtor(null, WithDtor()))));
+ static assert(is(typeof(emplace!WithDtor(null))));
+}
+
+// Doesn't call a destructor on uninitialized elements
+@nogc nothrow pure @system unittest
+{
+ static struct SWithDtor
+ {
+ private bool canBeInvoked = false;
+ ~this() @nogc nothrow pure @safe
+ {
+ assert(this.canBeInvoked);
+ }
+ }
+ void[SWithDtor.sizeof] memory = void;
+ auto actual = emplace!SWithDtor(memory[], SWithDtor(true));
+ assert(actual.canBeInvoked);
+}
+
+// Initializes structs if no arguments are given
+@nogc nothrow pure @safe unittest
+{
+ static struct SEntry
+ {
+ byte content;
+ }
+ ubyte[1] mem = [3];
+
+ assert(emplace!SEntry(cast(void[]) mem[0 .. 1]).content == 0);
+}
+
+// Postblit is called when emplacing a struct
+@nogc nothrow pure @system unittest
+{
+ static struct S
+ {
+ bool called = false;
+ this(this) @nogc nothrow pure @safe
+ {
+ this.called = true;
+ }
+ }
+ S target;
+ S* sp = &target;
+
+ emplace!S(sp[0 .. 1], S());
+ assert(target.called);
+}
+
+private void deinitialize(bool zero, T)(ref T value)
+{
+ static if (is(T == U[S], U, size_t S))
+ {
+ foreach (ref e; value)
+ {
+ deinitialize!zero(e);
+ }
+ }
+ else
+ {
+ import tanya.memory.op : copy, fill;
+
+ static if (isNested!T)
+ {
+ // Don't override the context pointer.
+ enum size_t size = T.sizeof - (void*).sizeof;
+ }
+ else
+ {
+ enum size_t size = T.sizeof;
+ }
+ static if (zero)
+ {
+ fill!0((cast(void*) &value)[0 .. size]);
+ }
+ else
+ {
+ copy(typeid(T).initializer()[0 .. size], (&value)[0 .. 1]);
+ }
+ }
+}
+
+/**
+ * Moves $(D_PARAM source) into $(D_PARAM target) assuming that
+ * $(D_PARAM target) isn't initialized.
+ *
+ * Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
+ * the $(D_PARAM source) into a valid but unspecified state, which means that
+ * after moving $(D_PARAM source) can be destroyed or assigned a new value, but
+ * accessing it yields an unspecified value. No postblits or destructors are
+ * called. If the $(D_PARAM target) should be destroyed before, use
+ * $(D_PSYMBOL move).
+ *
+ * $(D_PARAM source) and $(D_PARAM target) must be different objects.
+ *
+ * Params:
+ * T = Object type.
+ * source = Source object.
+ * target = Target object.
+ *
+ * See_Also: $(D_PSYMBOL move),
+ * $(D_PSYMBOL hasElaborateCopyConstructor),
+ * $(D_PSYMBOL hasElaborateDestructor).
+ *
+ * Precondition: `&source !is &target`.
+ */
+void moveEmplace(T)(ref T source, ref T target) @system
+in
+{
+ assert(&source !is &target, "Source and target must be different");
+}
+do
+{
+ static if (is(T == struct) || isStaticArray!T)
+ {
+ import tanya.memory.op : copy;
+
+ copy((&source)[0 .. 1], (&target)[0 .. 1]);
+
+ static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
+ {
+ static if (__VERSION__ >= 2083) // __traits(isZeroInit) available.
+ {
+ deinitialize!(__traits(isZeroInit, T))(source);
+ }
+ else
+ {
+ if (typeid(T).initializer().ptr is null)
+ {
+ deinitialize!true(source);
+ }
+ else
+ {
+ deinitialize!false(source);
+ }
+ }
+ }
+ }
+ else
+ {
+ target = source;
+ }
+}
+
+///
+@nogc nothrow pure @system unittest
+{
+ static struct S
+ {
+ int member = 5;
+
+ this(this) @nogc nothrow pure @safe
+ {
+ assert(false);
+ }
+ }
+ S source, target = void;
+ moveEmplace(source, target);
+ assert(target.member == 5);
+
+ int x1 = 5, x2;
+ moveEmplace(x1, x2);
+ assert(x2 == 5);
+}
+
+// Is pure.
+@nogc nothrow pure @system unittest
+{
+ struct S
+ {
+ this(this)
+ {
+ }
+ }
+ S source, target = void;
+ static assert(is(typeof({ moveEmplace(source, target); })));
+}
+
+// Moves nested.
+@nogc nothrow pure @system unittest
+{
+ struct Nested
+ {
+ void method() @nogc nothrow pure @safe
+ {
+ }
+ }
+ Nested source, target = void;
+ moveEmplace(source, target);
+ assert(source == target);
+}
+
+// Emplaces static arrays.
+@nogc nothrow pure @system unittest
+{
+ static struct S
+ {
+ size_t member;
+ this(size_t i) @nogc nothrow pure @safe
+ {
+ this.member = i;
+ }
+ ~this() @nogc nothrow pure @safe
+ {
+ }
+ }
+ S[2] source = [ S(5), S(5) ], target = void;
+ moveEmplace(source, target);
+ assert(source[0].member == 0);
+ assert(target[0].member == 5);
+ assert(source[1].member == 0);
+ assert(target[1].member == 5);
+}
+
+/**
+ * Moves $(D_PARAM source) into $(D_PARAM target) assuming that
+ * $(D_PARAM target) isn't initialized.
+ *
+ * Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
+ * the $(D_PARAM source) into a valid but unspecified state, which means that
+ * after moving $(D_PARAM source) can be destroyed or assigned a new value, but
+ * accessing it yields an unspecified value. $(D_PARAM target) is destroyed before
+ * the new value is assigned. If $(D_PARAM target) isn't initialized and
+ * therefore shouldn't be destroyed, $(D_PSYMBOL moveEmplace) can be used.
+ *
+ * If $(D_PARAM target) isn't specified, $(D_PSYMBOL move) returns the source
+ * as rvalue without calling its copy constructor or destructor.
+ *
+ * $(D_PARAM source) and $(D_PARAM target) are the same object,
+ * $(D_PSYMBOL move) does nothing.
+ *
+ * Params:
+ * T = Object type.
+ * source = Source object.
+ * target = Target object.
+ *
+ * See_Also: $(D_PSYMBOL moveEmplace).
+ */
+void move(T)(ref T source, ref T target)
+{
+ if ((() @trusted => &source is &target)())
+ {
+ return;
+ }
+ static if (hasElaborateDestructor!T)
+ {
+ target.__xdtor();
+ }
+ (() @trusted => moveEmplace(source, target))();
+}
+
+/// ditto
+T move(T)(ref T source) @trusted
+{
+ static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
+ {
+ T target = void;
+ moveEmplace(source, target);
+ return target;
+ }
+ else
+ {
+ return source;
+ }
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ static struct S
+ {
+ int member = 5;
+
+ this(this) @nogc nothrow pure @safe
+ {
+ assert(false);
+ }
+ }
+ S source, target = void;
+ move(source, target);
+ assert(target.member == 5);
+ assert(move(target).member == 5);
+
+ int x1 = 5, x2;
+ move(x1, x2);
+ assert(x2 == 5);
+ assert(move(x2) == 5);
+}
+
+// Moves if source is target.
+@nogc nothrow pure @safe unittest
+{
+ int x = 5;
+ move(x, x);
+ assert(x == 5);
+}
+
+/**
+ * Exchanges the values of $(D_PARAM a) and $(D_PARAM b).
+ *
+ * $(D_PSYMBOL swap) moves the contents of $(D_PARAM a) and $(D_PARAM b)
+ * without calling its postblits or destructors.
+ *
+ * Params:
+ * a = The first object.
+ * b = The second object.
+ */
+void swap(T)(ref T a, ref T b) @trusted
+{
+ T tmp = void;
+ moveEmplace(a, tmp);
+ moveEmplace(b, a);
+ moveEmplace(tmp, b);
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ int a = 3, b = 5;
+ swap(a, b);
+ assert(a == 5);
+ assert(b == 3);
+}
+
+/**
+ * Forwards its argument list preserving $(D_KEYWORD ref) and $(D_KEYWORD out)
+ * storage classes.
+ *
+ * $(D_PSYMBOL forward) accepts a list of variables or literals. It returns an
+ * argument list of the same length that can be for example passed to a
+ * function accepting the arguments of this type.
+ *
+ * Params:
+ * args = Argument list.
+ *
+ * Returns: $(D_PARAM args) with their original storage classes.
+ */
+template forward(args...)
+{
+ static if (args.length == 0)
+ {
+ alias forward = AliasSeq!();
+ }
+ else static if (__traits(isRef, args[0]) || __traits(isOut, args[0]))
+ {
+ static if (args.length == 1)
+ {
+ alias forward = args[0];
+ }
+ else
+ {
+ alias forward = AliasSeq!(args[0], forward!(args[1 .. $]));
+ }
+ }
+ else
+ {
+ @property auto forwardOne()
+ {
+ return move(args[0]);
+ }
+ static if (args.length == 1)
+ {
+ alias forward = forwardOne;
+ }
+ else
+ {
+ alias forward = AliasSeq!(forwardOne, forward!(args[1 .. $]));
+ }
+ }
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ static assert(is(typeof((int i) { int v = forward!i; })));
+ static assert(is(typeof((ref int i) { int v = forward!i; })));
+ static assert(is(typeof({
+ void f(int i, ref int j, out int k)
+ {
+ f(forward!(i, j, k));
+ }
+ })));
+}
diff --git a/source/tanya/memory/mallocator.d b/memory/tanya/memory/mallocator.d
index fdf7ede..858ad40 100644
--- a/source/tanya/memory/mallocator.d
+++ b/memory/tanya/memory/mallocator.d
@@ -10,7 +10,7 @@
* 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/mallocator.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/mallocator.d,
* tanya/memory/mallocator.d)
*/
module tanya.memory.mallocator;
diff --git a/source/tanya/memory/mmappool.d b/memory/tanya/memory/mmappool.d
index 5c42241..1bc401b 100644
--- a/source/tanya/memory/mmappool.d
+++ b/memory/tanya/memory/mmappool.d
@@ -9,7 +9,7 @@
* 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/mmappool.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/mmappool.d,
* tanya/memory/mmappool.d)
*/
module tanya.memory.mmappool;
@@ -398,7 +398,7 @@ final class MmapPool : Allocator
}
if (p !is null)
{
- copy(p[0 .. min(p.length, size)], reallocP);
+ copy(p[0 .. p.length < size ? p.length : size], reallocP);
deallocate(p);
}
p = reallocP;
diff --git a/source/tanya/memory/op.d b/memory/tanya/memory/op.d
index 6005329..d77f3bb 100644
--- a/source/tanya/memory/op.d
+++ b/memory/tanya/memory/op.d
@@ -9,7 +9,7 @@
* 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/op.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/op.d,
* tanya/memory/op.d)
*/
module tanya.memory.op;
diff --git a/source/tanya/memory/package.d b/memory/tanya/memory/package.d
index 8526b5a..98aec48 100644
--- a/source/tanya/memory/package.d
+++ b/memory/tanya/memory/package.d
@@ -9,15 +9,16 @@
* 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/package.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/package.d,
* tanya/memory/package.d)
*/
module tanya.memory;
-import tanya.conv;
public import tanya.memory.allocator;
public import tanya.memory.lifecycle;
import tanya.meta.trait;
+deprecated("Use tanya.meta.trait.stateSize instead")
+public import tanya.meta.trait : stateSize;
/**
* The mixin generates common methods for classes and structs using
@@ -37,11 +38,7 @@ mixin template DefaultAllocator()
* Precondition: $(D_INLINECODE allocator_ !is null)
*/
this(shared Allocator allocator) @nogc nothrow pure @safe
- in
- {
- assert(allocator !is null);
- }
- do
+ in (allocator !is null)
{
this.allocator_ = allocator;
}
@@ -55,11 +52,7 @@ mixin template DefaultAllocator()
* Postcondition: $(D_INLINECODE allocator !is null)
*/
@property shared(Allocator) allocator() @nogc nothrow pure @safe
- out (allocator)
- {
- assert(allocator !is null);
- }
- do
+ out (allocator; allocator !is null)
{
if (allocator_ is null)
{
@@ -70,11 +63,7 @@ mixin template DefaultAllocator()
/// ditto
@property shared(Allocator) allocator() const @nogc nothrow pure @trusted
- out (allocator)
- {
- assert(allocator !is null);
- }
- do
+ out (allocator; allocator !is null)
{
if (allocator_ is null)
{
@@ -110,11 +99,7 @@ private shared(Allocator) getAllocatorInstance() @nogc nothrow
* Postcondition: $(D_INLINECODE allocator !is null).
*/
@property shared(Allocator) defaultAllocator() @nogc nothrow pure @trusted
-out (allocator)
-{
- assert(allocator !is null);
-}
-do
+out (allocator; allocator !is null)
{
return (cast(GetPureInstance!Allocator) &getAllocatorInstance)();
}
@@ -128,68 +113,12 @@ do
* Precondition: $(D_INLINECODE allocator !is null).
*/
@property void defaultAllocator(shared(Allocator) allocator) @nogc nothrow @safe
-in
-{
- assert(allocator !is null);
-}
-do
+in (allocator !is null)
{
.allocator = allocator;
}
/**
- * Returns the size in bytes of the state that needs to be allocated to hold an
- * object of type $(D_PARAM T).
- *
- * There is a difference between the `.sizeof`-property and
- * $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface.
- * `T.sizeof` is constant on the given architecture then and is the same as
- * `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and
- * interfaces are reference types and `.sizeof` returns the size of the
- * reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize)
- * returns the size of the instance itself.
- *
- * The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array
- * stores its length and a data pointer. The size of the static arrays is
- * calculated differently since they are value types. It is the array length
- * multiplied by the element size.
- *
- * `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym
- * for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`.
- *
- * Params:
- * T = Object type.
- *
- * Returns: Size of an instance of type $(D_PARAM T).
- */
-template stateSize(T)
-{
- static if (isPolymorphicType!T)
- {
- enum size_t stateSize = __traits(classInstanceSize, T);
- }
- else
- {
- enum size_t stateSize = T.sizeof;
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static assert(stateSize!int == 4);
- static assert(stateSize!bool == 1);
- static assert(stateSize!(int[]) == (size_t.sizeof * 2));
- static assert(stateSize!(short[3]) == 6);
-
- static struct Empty
- {
- }
- static assert(stateSize!Empty == 1);
- static assert(stateSize!void == 1);
-}
-
-/**
* Params:
* size = Raw size.
* alignment = Alignment.
diff --git a/source/tanya/memory/smartref.d b/memory/tanya/memory/smartref.d
index 90271e7..1fe81f3 100644
--- a/source/tanya/memory/smartref.d
+++ b/memory/tanya/memory/smartref.d
@@ -18,21 +18,18 @@
* 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/smartref.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/smartref.d,
* tanya/memory/smartref.d)
*/
module tanya.memory.smartref;
-import tanya.algorithm.mutation;
-import tanya.conv;
import tanya.memory;
import tanya.meta.trait;
-import tanya.range.primitive;
version (unittest) import tanya.test.stub;
private template Payload(T)
{
- static if (isPolymorphicType!T || isArray!T)
+ static if (isPolymorphicType!T || isDynamicArray!T)
{
alias Payload = T;
}
@@ -529,23 +526,19 @@ do
*
* Params:
* T = Array type.
+ * E = Array element type.
* size = Array size.
* allocator = Allocator.
*
* Returns: Newly created $(D_PSYMBOL RefCounted!T).
*
* Precondition: $(D_INLINECODE allocator !is null
- * && size <= size_t.max / ElementType!T.sizeof)
+ * && size <= size_t.max / E.sizeof)
*/
-RefCounted!T refCounted(T)(shared Allocator allocator, const size_t size)
+RefCounted!T refCounted(T : E[], E)(shared Allocator allocator, size_t size)
@trusted
-if (isArray!T)
-in
-{
- assert(allocator !is null);
- assert(size <= size_t.max / ElementType!T.sizeof);
-}
-do
+in (allocator !is null)
+in (size <= size_t.max / E.sizeof)
{
return RefCounted!T(allocator.make!T(size), allocator);
}
@@ -852,25 +845,21 @@ do
*
* Params:
* T = Array type.
+ * E = Array element type.
* size = Array size.
* allocator = Allocator.
*
* Returns: Newly created $(D_PSYMBOL Unique!T).
*
* Precondition: $(D_INLINECODE allocator !is null
- * && size <= size_t.max / ElementType!T.sizeof)
+ * && size <= size_t.max / E.sizeof)
*/
-Unique!T unique(T)(shared Allocator allocator, const size_t size)
+Unique!T unique(T : E[], E)(shared Allocator allocator, size_t size)
@trusted
-if (isArray!T)
-in
-{
- assert(allocator !is null);
- assert(size <= size_t.max / ElementType!T.sizeof);
-}
-do
+in (allocator !is null)
+in (size <= size_t.max / E.sizeof)
{
- auto payload = allocator.resize!(ElementType!T)(null, size);
+ auto payload = allocator.resize!E(null, size);
return Unique!T(payload, allocator);
}
diff --git a/source/tanya/test/assertion.d b/memory/tanya/test/assertion.d
index 10105d7..10105d7 100644
--- a/source/tanya/test/assertion.d
+++ b/memory/tanya/test/assertion.d
diff --git a/source/tanya/test/package.d b/memory/tanya/test/package.d
index ab6f861..ab6f861 100644
--- a/source/tanya/test/package.d
+++ b/memory/tanya/test/package.d
diff --git a/source/tanya/test/stub.d b/memory/tanya/test/stub.d
index e1f8dcb..e1f8dcb 100644
--- a/source/tanya/test/stub.d
+++ b/memory/tanya/test/stub.d
diff --git a/meta/dub.json b/meta/dub.json
index c8d2ba7..663d2fd 100644
--- a/meta/dub.json
+++ b/meta/dub.json
@@ -1,5 +1,12 @@
{
"name": "meta",
"description": "Template metaprogramming",
- "targetType": "library"
+ "targetType": "library",
+
+ "sourcePaths": [
+ "."
+ ],
+ "importPaths": [
+ "."
+ ]
}
diff --git a/meta/source/tanya/meta/metafunction.d b/meta/tanya/meta/metafunction.d
index 6da6b47..a05b5cf 100644
--- a/meta/source/tanya/meta/metafunction.d
+++ b/meta/tanya/meta/metafunction.d
@@ -9,11 +9,11 @@
* It contains different algorithms for iterating, searching and modifying
* template arguments.
*
- * 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/meta/metafunction.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/metafunction.d,
* tanya/meta/metafunction.d)
*/
module tanya.meta.metafunction;
diff --git a/meta/source/tanya/meta/package.d b/meta/tanya/meta/package.d
index d93e4fa..f06a166 100644
--- a/meta/source/tanya/meta/package.d
+++ b/meta/tanya/meta/package.d
@@ -9,11 +9,11 @@
* to transform from one type to another. It has also different algorithms for
* iterating, searching and modifying template arguments.
*
- * 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/meta/package.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/package.d,
* tanya/meta/package.d)
*/
module tanya.meta;
diff --git a/meta/source/tanya/meta/trait.d b/meta/tanya/meta/trait.d
index 69b97b9..ebea9ce 100644
--- a/meta/source/tanya/meta/trait.d
+++ b/meta/tanya/meta/trait.d
@@ -8,11 +8,11 @@
* Templates in this module are used to obtain type information at compile
* time.
*
- * 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/meta/trait.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/trait.d,
* tanya/meta/trait.d)
*/
module tanya.meta.trait;
@@ -2693,6 +2693,58 @@ if (is(T == class))
}
/**
+ * Returns the size in bytes of the state that needs to be allocated to hold an
+ * object of type $(D_PARAM T).
+ *
+ * There is a difference between the `.sizeof`-property and
+ * $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface.
+ * `T.sizeof` is constant on the given architecture then and is the same as
+ * `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and
+ * interfaces are reference types and `.sizeof` returns the size of the
+ * reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize)
+ * returns the size of the instance itself.
+ *
+ * The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array
+ * stores its length and a data pointer. The size of the static arrays is
+ * calculated differently since they are value types. It is the array length
+ * multiplied by the element size.
+ *
+ * `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym
+ * for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`.
+ *
+ * Params:
+ * T = Object type.
+ *
+ * Returns: Size of an instance of type $(D_PARAM T).
+ */
+template stateSize(T)
+{
+ static if (isPolymorphicType!T)
+ {
+ enum size_t stateSize = __traits(classInstanceSize, T);
+ }
+ else
+ {
+ enum size_t stateSize = T.sizeof;
+ }
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ static assert(stateSize!int == 4);
+ static assert(stateSize!bool == 1);
+ static assert(stateSize!(int[]) == (size_t.sizeof * 2));
+ static assert(stateSize!(short[3]) == 6);
+
+ static struct Empty
+ {
+ }
+ static assert(stateSize!Empty == 1);
+ static assert(stateSize!void == 1);
+}
+
+/**
* Tests whether $(D_INLINECODE pred(T)) can be used as condition in an
* $(D_KEYWORD if)-statement or a ternary operator.
*
diff --git a/meta/source/tanya/meta/transform.d b/meta/tanya/meta/transform.d
index 5697e69..083e7ee 100644
--- a/meta/source/tanya/meta/transform.d
+++ b/meta/tanya/meta/transform.d
@@ -9,11 +9,11 @@
* types. They take some type as argument and return a different type after
* perfoming the specified transformation.
*
- * 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/meta/transform.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/transform.d,
* tanya/meta/transform.d)
*/
module tanya.meta.transform;
diff --git a/os/dub.json b/os/dub.json
index 87df29d..647e24d 100644
--- a/os/dub.json
+++ b/os/dub.json
@@ -5,5 +5,12 @@
"dependencies": {
"tanya:meta": "*"
- }
+ },
+
+ "sourcePaths": [
+ "."
+ ],
+ "importPaths": [
+ "."
+ ]
}
diff --git a/os/source/tanya/os/error.d b/os/tanya/os/error.d
index b80404a..31c0102 100644
--- a/os/source/tanya/os/error.d
+++ b/os/tanya/os/error.d
@@ -9,7 +9,7 @@
* 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/os/error.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/os/tanya/os/error.d,
* tanya/os/error.d)
*/
module tanya.os.error;
diff --git a/os/source/tanya/os/package.d b/os/tanya/os/package.d
index c472c05..070ec44 100644
--- a/os/source/tanya/os/package.d
+++ b/os/tanya/os/package.d
@@ -10,7 +10,7 @@
* 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/os/package.d,
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/os/tanya/os/package.d,
* tanya/os/package.d)
*/
module tanya.os;
diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d
index 7eae9cd..fcfb1c0 100644
--- a/source/tanya/algorithm/iteration.d
+++ b/source/tanya/algorithm/iteration.d
@@ -21,7 +21,7 @@
module tanya.algorithm.iteration;
import tanya.algorithm.comparison;
-import tanya.algorithm.mutation;
+import tanya.memory.lifecycle;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d
index f0c156d..ddb2743 100644
--- a/source/tanya/algorithm/mutation.d
+++ b/source/tanya/algorithm/mutation.d
@@ -14,284 +14,21 @@
*/
module tanya.algorithm.mutation;
-import tanya.conv;
static import tanya.memory.op;
+static import tanya.memory.lifecycle;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range;
version (unittest) import tanya.test.stub;
-private void deinitialize(bool zero, T)(ref T value)
-{
- static if (is(T == U[S], U, size_t S))
- {
- foreach (ref e; value)
- {
- deinitialize!zero(e);
- }
- }
- else
- {
- static if (isNested!T)
- {
- // Don't override the context pointer.
- enum size_t size = T.sizeof - (void*).sizeof;
- }
- else
- {
- enum size_t size = T.sizeof;
- }
- static if (zero)
- {
- tanya.memory.op.fill!0((cast(void*) &value)[0 .. size]);
- }
- else
- {
- tanya.memory.op.copy(typeid(T).initializer()[0 .. size],
- (&value)[0 .. 1]);
- }
- }
-}
-
-/**
- * Moves $(D_PARAM source) into $(D_PARAM target) assuming that
- * $(D_PARAM target) isn't initialized.
- *
- * Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
- * the $(D_PARAM source) into a valid but unspecified state, which means that
- * after moving $(D_PARAM source) can be destroyed or assigned a new value, but
- * accessing it yields an unspecified value. No postblits or destructors are
- * called. If the $(D_PARAM target) should be destroyed before, use
- * $(D_PSYMBOL move).
- *
- * $(D_PARAM source) and $(D_PARAM target) must be different objects.
- *
- * Params:
- * T = Object type.
- * source = Source object.
- * target = Target object.
- *
- * See_Also: $(D_PSYMBOL move),
- * $(D_PSYMBOL hasElaborateCopyConstructor),
- * $(D_PSYMBOL hasElaborateDestructor).
- *
- * Precondition: `&source !is &target`.
- */
-void moveEmplace(T)(ref T source, ref T target) @system
-in
-{
- assert(&source !is &target, "Source and target must be different");
-}
-do
-{
- static if (is(T == struct) || isStaticArray!T)
- {
- tanya.memory.op.copy((&source)[0 .. 1], (&target)[0 .. 1]);
-
- static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
- {
- static if (__VERSION__ >= 2083) // __traits(isZeroInit) available.
- {
- deinitialize!(__traits(isZeroInit, T))(source);
- }
- else
- {
- if (typeid(T).initializer().ptr is null)
- {
- deinitialize!true(source);
- }
- else
- {
- deinitialize!false(source);
- }
- }
- }
- }
- else
- {
- target = source;
- }
-}
-
-///
-@nogc nothrow pure @system unittest
-{
- static struct S
- {
- int member = 5;
-
- this(this) @nogc nothrow pure @safe
- {
- assert(false);
- }
- }
- S source, target = void;
- moveEmplace(source, target);
- assert(target.member == 5);
+deprecated("Use tanya.memory.lifecycle.swap instead")
+alias swap = tanya.memory.lifecycle.swap;
- int x1 = 5, x2;
- moveEmplace(x1, x2);
- assert(x2 == 5);
-}
+deprecated("Use tanya.memory.lifecycle.moveEmplace instead")
+alias moveEmplace = tanya.memory.lifecycle.moveEmplace;
-// Is pure.
-@nogc nothrow pure @system unittest
-{
- struct S
- {
- this(this)
- {
- }
- }
- S source, target = void;
- static assert(is(typeof({ moveEmplace(source, target); })));
-}
-
-// Moves nested.
-@nogc nothrow pure @system unittest
-{
- struct Nested
- {
- void method() @nogc nothrow pure @safe
- {
- }
- }
- Nested source, target = void;
- moveEmplace(source, target);
- assert(source == target);
-}
-
-// Emplaces static arrays.
-@nogc nothrow pure @system unittest
-{
- static struct S
- {
- size_t member;
- this(size_t i) @nogc nothrow pure @safe
- {
- this.member = i;
- }
- ~this() @nogc nothrow pure @safe
- {
- }
- }
- S[2] source = [ S(5), S(5) ], target = void;
- moveEmplace(source, target);
- assert(source[0].member == 0);
- assert(target[0].member == 5);
- assert(source[1].member == 0);
- assert(target[1].member == 5);
-}
-
-/**
- * Moves $(D_PARAM source) into $(D_PARAM target) assuming that
- * $(D_PARAM target) isn't initialized.
- *
- * Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
- * the $(D_PARAM source) into a valid but unspecified state, which means that
- * after moving $(D_PARAM source) can be destroyed or assigned a new value, but
- * accessing it yields an unspecified value. $(D_PARAM target) is destroyed before
- * the new value is assigned. If $(D_PARAM target) isn't initialized and
- * therefore shouldn't be destroyed, $(D_PSYMBOL moveEmplace) can be used.
- *
- * If $(D_PARAM target) isn't specified, $(D_PSYMBOL move) returns the source
- * as rvalue without calling its copy constructor or destructor.
- *
- * $(D_PARAM source) and $(D_PARAM target) are the same object,
- * $(D_PSYMBOL move) does nothing.
- *
- * Params:
- * T = Object type.
- * source = Source object.
- * target = Target object.
- *
- * See_Also: $(D_PSYMBOL moveEmplace).
- */
-void move(T)(ref T source, ref T target)
-{
- if ((() @trusted => &source is &target)())
- {
- return;
- }
- static if (hasElaborateDestructor!T)
- {
- target.__xdtor();
- }
- (() @trusted => moveEmplace(source, target))();
-}
-
-/// ditto
-T move(T)(ref T source) @trusted
-{
- static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
- {
- T target = void;
- moveEmplace(source, target);
- return target;
- }
- else
- {
- return source;
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static struct S
- {
- int member = 5;
-
- this(this) @nogc nothrow pure @safe
- {
- assert(false);
- }
- }
- S source, target = void;
- move(source, target);
- assert(target.member == 5);
- assert(move(target).member == 5);
-
- int x1 = 5, x2;
- move(x1, x2);
- assert(x2 == 5);
- assert(move(x2) == 5);
-}
-
-// Moves if source is target.
-@nogc nothrow pure @safe unittest
-{
- int x = 5;
- move(x, x);
- assert(x == 5);
-}
-
-/**
- * Exchanges the values of $(D_PARAM a) and $(D_PARAM b).
- *
- * $(D_PSYMBOL swap) moves the contents of $(D_PARAM a) and $(D_PARAM b)
- * without calling its postblits or destructors.
- *
- * Params:
- * a = The first object.
- * b = The second object.
- */
-void swap(T)(ref T a, ref T b) @trusted
-{
- T tmp = void;
- moveEmplace(a, tmp);
- moveEmplace(b, a);
- moveEmplace(tmp, b);
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- int a = 3, b = 5;
- swap(a, b);
- assert(a == 5);
- assert(b == 3);
-}
+deprecated("Use tanya.memory.lifecycle.move instead")
+alias move = tanya.memory.lifecycle.move;
/**
* Copies the $(D_PARAM source) range into the $(D_PARAM target) range.
@@ -494,7 +231,7 @@ if (isInputRange!Range && hasLvalueElements!Range
for (; !range.empty; range.popFront())
{
ElementType!Range* p = &range.front;
- emplace!(ElementType!Range)(cast(void[]) (p[0 .. 1]), value);
+ tanya.memory.lifecycle.emplace!(ElementType!Range)(cast(void[]) (p[0 .. 1]), value);
}
}
else
@@ -577,13 +314,7 @@ if (isInputRange!Range && hasLvalueElements!Range)
void destroyAll(Range)(Range range)
if (isInputRange!Range && hasLvalueElements!Range)
{
- static if (hasElaborateDestructor!(ElementType!Range))
- {
- foreach (ref e; range)
- {
- destroy(e);
- }
- }
+ tanya.memory.lifecycle.destroyAllImpl!(Range, ElementType!Range)(range);
}
///
@@ -632,7 +363,7 @@ if (isForwardRange!Range && hasSwappableElements!Range)
while (!front.empty && !next.empty && !sameHead(front, next))
{
- swap(front.front, next.front);
+ tanya.memory.lifecycle.swap(front.front, next.front);
front.popFront();
next.popFront();
diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d
index 2b3adfa..1c6842f 100644
--- a/source/tanya/container/array.d
+++ b/source/tanya/container/array.d
@@ -17,7 +17,6 @@ module tanya.container.array;
import core.checkedint;
import tanya.algorithm.comparison;
import tanya.algorithm.mutation;
-import tanya.functional;
import tanya.memory;
import tanya.meta.trait;
import tanya.meta.transform;
diff --git a/source/tanya/container/entry.d b/source/tanya/container/entry.d
index 1e7e28f..408849a 100644
--- a/source/tanya/container/entry.d
+++ b/source/tanya/container/entry.d
@@ -14,9 +14,9 @@
*/
module tanya.container.entry;
-import tanya.algorithm.mutation;
import tanya.container.array;
import tanya.memory.allocator;
+import tanya.memory.lifecycle;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.typecons;
diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d
index 09a5c9f..e6e01d5 100644
--- a/source/tanya/container/list.d
+++ b/source/tanya/container/list.d
@@ -16,7 +16,6 @@
module tanya.container.list;
import tanya.algorithm.comparison;
-import tanya.algorithm.mutation;
import tanya.container.entry;
import tanya.memory;
import tanya.meta.trait;
diff --git a/source/tanya/conv.d b/source/tanya/conv.d
index a78c2bb..f602e01 100644
--- a/source/tanya/conv.d
+++ b/source/tanya/conv.d
@@ -14,15 +14,13 @@
*/
module tanya.conv;
-import tanya.algorithm.mutation;
import tanya.container.string;
-import tanya.format;
import tanya.memory;
-import tanya.memory.op;
+deprecated("Use tanya.memory.lifecycle.emplace instead")
+public import tanya.memory.lifecycle : emplace;
import tanya.meta.trait;
import tanya.meta.transform;
-import tanya.range.array;
-import tanya.range.primitive;
+import tanya.range;
version (unittest)
{
@@ -31,269 +29,6 @@ version (unittest)
}
/**
- * Constructs a new object of type $(D_PARAM T) in $(D_PARAM memory) with the
- * given arguments.
- *
- * If $(D_PARAM T) is a $(D_KEYWORD class), emplace returns a class reference
- * of type $(D_PARAM T), otherwise a pointer to the constructed object is
- * returned.
- *
- * If $(D_PARAM T) is a nested class inside another class, $(D_PARAM outer)
- * should be an instance of the outer class.
- *
- * $(D_PARAM args) are arguments for the constructor of $(D_PARAM T). If
- * $(D_PARAM T) isn't an aggregate type and doesn't have a constructor,
- * $(D_PARAM memory) can be initialized to `args[0]` if `Args.length == 1`,
- * `Args[0]` should be implicitly convertible to $(D_PARAM T) then.
- *
- * Params:
- * T = Constructed type.
- * U = Type of the outer class if $(D_PARAM T) is a nested class.
- * Args = Types of the constructor arguments if $(D_PARAM T) has a constructor
- * or the type of the initial value.
- * outer = Outer class instance if $(D_PARAM T) is a nested class.
- * args = Constructor arguments if $(D_PARAM T) has a constructor or the
- * initial value.
- *
- * Returns: New instance of type $(D_PARAM T) constructed in $(D_PARAM memory).
- *
- * Precondition: `memory.length == stateSize!T`.
- * Postcondition: $(D_PARAM memory) and the result point to the same memory.
- */
-T emplace(T, U, Args...)(void[] memory, U outer, auto ref Args args)
-if (!isAbstractClass!T && isInnerClass!T && is(typeof(T.outer) == U))
-in (memory.length >= stateSize!T)
-out (result; memory.ptr is (() @trusted => cast(void*) result)())
-{
- copy(typeid(T).initializer, memory);
-
- auto result = (() @trusted => cast(T) memory.ptr)();
- result.outer = outer;
-
- static if (is(typeof(result.__ctor(args))))
- {
- result.__ctor(args);
- }
-
- return result;
-}
-
-/// ditto
-T emplace(T, Args...)(void[] memory, auto ref Args args)
-if (is(T == class) && !isAbstractClass!T && !isInnerClass!T)
-in (memory.length == stateSize!T)
-out (result; memory.ptr is (() @trusted => cast(void*) result)())
-{
- copy(typeid(T).initializer, memory);
-
- auto result = (() @trusted => cast(T) memory.ptr)();
- static if (is(typeof(result.__ctor(args))))
- {
- result.__ctor(args);
- }
- return result;
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- import tanya.memory : stateSize;
-
- class C
- {
- int i = 5;
- class Inner
- {
- int i;
-
- this(int param) pure nothrow @safe @nogc
- {
- this.i = param;
- }
- }
- }
- ubyte[stateSize!C] memory1;
- ubyte[stateSize!(C.Inner)] memory2;
-
- auto c = emplace!C(memory1);
- assert(c.i == 5);
-
- auto inner = emplace!(C.Inner)(memory2, c, 8);
- assert(c.i == 5);
- assert(inner.i == 8);
- assert(inner.outer is c);
-}
-
-/// ditto
-T* emplace(T, Args...)(void[] memory, auto ref Args args)
-if (!isAggregateType!T && (Args.length <= 1))
-in (memory.length >= T.sizeof)
-out (result; memory.ptr is result)
-{
- auto result = (() @trusted => cast(T*) memory.ptr)();
- static if (Args.length == 1)
- {
- *result = T(args[0]);
- }
- else
- {
- *result = T.init;
- }
- return result;
-}
-
-private void initializeOne(T)(ref void[] memory, ref T* result) @trusted
-{
- static if (!hasElaborateAssign!T && isAssignable!T)
- {
- *result = T.init;
- }
- else static if (__VERSION__ >= 2083 // __traits(isZeroInit) available.
- && __traits(isZeroInit, T))
- {
- memory.ptr[0 .. T.sizeof].fill!0;
- }
- else
- {
- static immutable T init = T.init;
- copy((&init)[0 .. 1], memory);
- }
-}
-
-/// ditto
-T* emplace(T, Args...)(void[] memory, auto ref Args args)
-if (!isPolymorphicType!T && isAggregateType!T)
-in (memory.length >= T.sizeof)
-out (result; memory.ptr is result)
-{
- auto result = (() @trusted => cast(T*) memory.ptr)();
-
- static if (Args.length == 0)
- {
- static assert(is(typeof({ static T t; })),
- "Default constructor is disabled");
- initializeOne(memory, result);
- }
- else static if (is(typeof(result.__ctor(args))))
- {
- initializeOne(memory, result);
- result.__ctor(args);
- }
- else static if (Args.length == 1 && is(typeof({ T t = args[0]; })))
- {
- ((ref arg) @trusted =>
- copy((cast(void*) &arg)[0 .. T.sizeof], memory))(args[0]);
- static if (hasElaborateCopyConstructor!T)
- {
- result.__postblit();
- }
- }
- else static if (is(typeof({ T t = T(args); })))
- {
- auto init = T(args);
- (() @trusted => moveEmplace(init, *result))();
- }
- else
- {
- static assert(false,
- "Unable to construct value with the given arguments");
- }
- return result;
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- ubyte[4] memory;
-
- auto i = emplace!int(memory);
- static assert(is(typeof(i) == int*));
- assert(*i == 0);
-
- i = emplace!int(memory, 5);
- assert(*i == 5);
-
- static struct S
- {
- int i;
- @disable this();
- @disable this(this);
- this(int i) @nogc nothrow pure @safe
- {
- this.i = i;
- }
- }
- auto s = emplace!S(memory, 8);
- static assert(is(typeof(s) == S*));
- assert(s.i == 8);
-}
-
-// Handles "Cannot access frame pointer" error.
-@nogc nothrow pure @safe unittest
-{
- struct F
- {
- ~this() @nogc nothrow pure @safe
- {
- }
- }
- static assert(is(typeof(emplace!F((void[]).init))));
-}
-
-// Can emplace structs without a constructor
-@nogc nothrow pure @safe unittest
-{
- static assert(is(typeof(emplace!WithDtor(null, WithDtor()))));
- static assert(is(typeof(emplace!WithDtor(null))));
-}
-
-// Doesn't call a destructor on uninitialized elements
-@nogc nothrow pure @system unittest
-{
- static struct SWithDtor
- {
- private bool canBeInvoked = false;
- ~this() @nogc nothrow pure @safe
- {
- assert(this.canBeInvoked);
- }
- }
- void[SWithDtor.sizeof] memory = void;
- auto actual = emplace!SWithDtor(memory[], SWithDtor(true));
- assert(actual.canBeInvoked);
-}
-
-// Initializes structs if no arguments are given
-@nogc nothrow pure @safe unittest
-{
- static struct SEntry
- {
- byte content;
- }
- ubyte[1] mem = [3];
-
- assert(emplace!SEntry(cast(void[]) mem[0 .. 1]).content == 0);
-}
-
-// Postblit is called when emplacing a struct
-@nogc nothrow pure @system unittest
-{
- static struct S
- {
- bool called = false;
- this(this) @nogc nothrow pure @safe
- {
- this.called = true;
- }
- }
- S target;
- S* sp = &target;
-
- emplace!S(sp[0 .. 1], S());
- assert(target.called);
-}
-
-/**
* Thrown if a type conversion fails.
*/
final class ConvException : Exception
diff --git a/source/tanya/functional.d b/source/tanya/functional.d
index f628a51..9a1c3a1 100644
--- a/source/tanya/functional.d
+++ b/source/tanya/functional.d
@@ -2,77 +2,17 @@
* 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/. */
-/**
+/*
* Functions that manipulate other functions and their argument lists.
*
- * 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)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/functional.d,
* tanya/functional.d)
*/
+deprecated("Use tanya.memory.lifecycle instead")
module tanya.functional;
-import tanya.algorithm.mutation;
-import tanya.meta.metafunction;
-
-/**
- * Forwards its argument list preserving $(D_KEYWORD ref) and $(D_KEYWORD out)
- * storage classes.
- *
- * $(D_PSYMBOL forward) accepts a list of variables or literals. It returns an
- * argument list of the same length that can be for example passed to a
- * function accepting the arguments of this type.
- *
- * Params:
- * args = Argument list.
- *
- * Returns: $(D_PARAM args) with their original storage classes.
- */
-template forward(args...)
-{
- static if (args.length == 0)
- {
- alias forward = AliasSeq!();
- }
- else static if (__traits(isRef, args[0]) || __traits(isOut, args[0]))
- {
- static if (args.length == 1)
- {
- alias forward = args[0];
- }
- else
- {
- alias forward = AliasSeq!(args[0], forward!(args[1 .. $]));
- }
- }
- else
- {
- @property auto forwardOne()
- {
- return move(args[0]);
- }
- static if (args.length == 1)
- {
- alias forward = forwardOne;
- }
- else
- {
- alias forward = AliasSeq!(forwardOne, forward!(args[1 .. $]));
- }
- }
-}
-
-///
-@nogc nothrow pure @safe unittest
-{
- static assert(is(typeof((int i) { int v = forward!i; })));
- static assert(is(typeof((ref int i) { int v = forward!i; })));
- static assert(is(typeof({
- void f(int i, ref int j, out int k)
- {
- f(forward!(i, j, k));
- }
- })));
-}
+public import tanya.memory.lifecycle : forward;
diff --git a/source/tanya/memory/lifecycle.d b/source/tanya/memory/lifecycle.d
deleted file mode 100644
index 2221af3..0000000
--- a/source/tanya/memory/lifecycle.d
+++ /dev/null
@@ -1,360 +0,0 @@
-/* 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/net/ip.d b/source/tanya/net/ip.d
index 2296eac..2afdfe8 100644
--- a/source/tanya/net/ip.d
+++ b/source/tanya/net/ip.d
@@ -21,6 +21,7 @@ import tanya.container.string;
import tanya.conv;
import tanya.encoding.ascii;
import tanya.format;
+import tanya.memory.lifecycle;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.net.iface;
diff --git a/source/tanya/range/adapter.d b/source/tanya/range/adapter.d
index 13f4c1e..bc20e10 100644
--- a/source/tanya/range/adapter.d
+++ b/source/tanya/range/adapter.d
@@ -15,7 +15,7 @@
module tanya.range.adapter;
import tanya.algorithm.mutation;
-import tanya.functional;
+import tanya.memory.lifecycle;
import tanya.meta.trait;
import tanya.range;
diff --git a/source/tanya/range/primitive.d b/source/tanya/range/primitive.d
index ae604e9..0b192b0 100644
--- a/source/tanya/range/primitive.d
+++ b/source/tanya/range/primitive.d
@@ -15,7 +15,7 @@
module tanya.range.primitive;
import tanya.algorithm.comparison;
-import tanya.algorithm.mutation;
+import tanya.memory.lifecycle;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.array;
diff --git a/source/tanya/typecons.d b/source/tanya/typecons.d
index 1407c62..fa09831 100644
--- a/source/tanya/typecons.d
+++ b/source/tanya/typecons.d
@@ -17,10 +17,8 @@
*/
module tanya.typecons;
-import tanya.algorithm.mutation;
-import tanya.conv;
import tanya.format;
-import tanya.functional;
+import tanya.memory.lifecycle;
import tanya.meta.metafunction;
import tanya.meta.trait;
version (unittest) import tanya.test.stub;
diff --git a/sys/dub.json b/sys/dub.json
index 8fb6d71..9201582 100644
--- a/sys/dub.json
+++ b/sys/dub.json
@@ -1,5 +1,12 @@
{
"name": "sys",
"description": "Low-level operating system bindings and definitions",
- "targetType": "library"
+ "targetType": "library",
+
+ "sourcePaths": [
+ "."
+ ],
+ "importPaths": [
+ "."
+ ]
}
diff --git a/sys/source/tanya/sys/linux/syscall.d b/sys/tanya/sys/linux/syscall.d
index ccc3fee..5c90ea5 100644
--- a/sys/source/tanya/sys/linux/syscall.d
+++ b/sys/tanya/sys/linux/syscall.d
@@ -7,8 +7,6 @@
* 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/sys/linux/syscall.d,
- * tanya/sys/linux/syscall.d)
*/
module tanya.sys.linux.syscall;
diff --git a/sys/source/tanya/sys/posix/ioctl.d b/sys/tanya/sys/posix/ioctl.d
index 86d1465..c206c89 100644
--- a/sys/source/tanya/sys/posix/ioctl.d
+++ b/sys/tanya/sys/posix/ioctl.d
@@ -7,8 +7,6 @@
* 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/sys/posix/ioctl.d,
- * tanya/sys/posix/ioctl.d)
*/
module tanya.sys.posix.ioctl;
diff --git a/sys/source/tanya/sys/posix/mman.d b/sys/tanya/sys/posix/mman.d
index 24a4701..21266ea 100644
--- a/sys/source/tanya/sys/posix/mman.d
+++ b/sys/tanya/sys/posix/mman.d
@@ -7,8 +7,6 @@
* 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/sys/posix/mman.d,
- * tanya/sys/posix/mman.d)
*/
module tanya.sys.posix.mman;
diff --git a/sys/source/tanya/sys/posix/net/if_.d b/sys/tanya/sys/posix/net/if_.d
index 1cb5b43..c9e3b86 100644
--- a/sys/source/tanya/sys/posix/net/if_.d
+++ b/sys/tanya/sys/posix/net/if_.d
@@ -7,8 +7,6 @@
* 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/sys/posix/net/if_.d,
- * tanya/sys/posix/net/if_.d)
*/
module tanya.sys.posix.net.if_;
diff --git a/sys/source/tanya/sys/posix/socket.d b/sys/tanya/sys/posix/socket.d
index 8924a8d..4f01a66 100644
--- a/sys/source/tanya/sys/posix/socket.d
+++ b/sys/tanya/sys/posix/socket.d
@@ -7,8 +7,6 @@
* 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/sys/posix/socket.d,
- * tanya/sys/posix/socket.d)
*/
module tanya.sys.posix.socket;
diff --git a/sys/source/tanya/sys/windows/def.d b/sys/tanya/sys/windows/def.d
index 84b4864..5b7ab59 100644
--- a/sys/source/tanya/sys/windows/def.d
+++ b/sys/tanya/sys/windows/def.d
@@ -20,8 +20,6 @@
* 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/sys/windows/def.d,
- * tanya/sys/windows/def.d)
*/
module tanya.sys.windows.def;
diff --git a/sys/source/tanya/sys/windows/ifdef.d b/sys/tanya/sys/windows/ifdef.d
index f091427..084b5ca 100644
--- a/sys/source/tanya/sys/windows/ifdef.d
+++ b/sys/tanya/sys/windows/ifdef.d
@@ -7,8 +7,6 @@
* 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/sys/windows/ifdef.d,
- * tanya/sys/windows/ifdef.d)
*/
module tanya.sys.windows.ifdef;
diff --git a/sys/source/tanya/sys/windows/iphlpapi.d b/sys/tanya/sys/windows/iphlpapi.d
index 37d0f16..450b265 100644
--- a/sys/source/tanya/sys/windows/iphlpapi.d
+++ b/sys/tanya/sys/windows/iphlpapi.d
@@ -7,8 +7,6 @@
* 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/sys/windows/iphlpapi.d,
- * tanya/sys/windows/iphlpapi.d)
*/
module tanya.sys.windows.iphlpapi;
diff --git a/sys/source/tanya/sys/windows/package.d b/sys/tanya/sys/windows/package.d
index 5e9b396..ef03e29 100644
--- a/sys/source/tanya/sys/windows/package.d
+++ b/sys/tanya/sys/windows/package.d
@@ -7,8 +7,6 @@
* 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/sys/windows/package.d,
- * tanya/sys/windows/package.d)
*/
module tanya.sys.windows;
diff --git a/sys/source/tanya/sys/windows/winbase.d b/sys/tanya/sys/windows/winbase.d
index 407b6d2..ba977eb 100644
--- a/sys/source/tanya/sys/windows/winbase.d
+++ b/sys/tanya/sys/windows/winbase.d
@@ -9,8 +9,6 @@
* 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/sys/windows/winbase.d,
- * tanya/sys/windows/winbase.d)
*/
module tanya.sys.windows.winbase;
diff --git a/sys/source/tanya/sys/windows/winsock2.d b/sys/tanya/sys/windows/winsock2.d
index 931e76b..1c6a452 100644
--- a/sys/source/tanya/sys/windows/winsock2.d
+++ b/sys/tanya/sys/windows/winsock2.d
@@ -9,8 +9,6 @@
* 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/sys/windows/winsock2.d,
- * tanya/sys/windows/winsock2.d)
*/
module tanya.sys.windows.winsock2;