summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/tanya/math/mp.d126
-rw-r--r--source/tanya/memory/package.d3
-rw-r--r--source/tanya/memory/types.d118
3 files changed, 138 insertions, 109 deletions
diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d
index 6da1027..10bf0a8 100644
--- a/source/tanya/math/mp.d
+++ b/source/tanya/math/mp.d
@@ -29,7 +29,7 @@ struct Integer
pure nothrow @safe @nogc invariant
{
- assert(rep.length || !sign, "0 should be positive.");
+ assert(!rep.count || rep.length || !sign, "0 should be positive.");
}
/**
@@ -39,18 +39,37 @@ struct Integer
* T = Value type.
* value = Initial value.
* allocator = Allocator.
+ *
+ * Precondition: $(D_INLINECODE allocator !is null)
*/
this(T)(in T value, shared Allocator allocator = defaultAllocator)
nothrow @safe @nogc
- if (isIntegral!T)
+ if (isIntegral!T || is(T == Integer))
+ {
+ this(allocator);
+ static if (isIntegral!T)
+ {
+ assignInt(value);
+ }
+ else
+ {
+ rep = RefCounted!(ubyte[])(() @trusted {
+ return cast(ubyte[]) allocator.allocate(value.length);
+ }(), allocator);
+ value.rep.get.copy(rep.get);
+ sign = value.sign;
+ }
+ }
+
+ /// Ditto.
+ this(shared Allocator allocator) nothrow @safe @nogc
in
{
assert(allocator !is null);
}
body
{
- this(allocator);
- assignInt(value);
+ this.allocator = allocator;
}
private @nogc unittest
@@ -66,30 +85,6 @@ struct Integer
assert(h2.sign);
}
- /// Ditto.
- this(T)(in T value, shared Allocator allocator = defaultAllocator)
- nothrow @safe @nogc
- if (is(T == Integer))
- in
- {
- assert(allocator !is null);
- }
- body
- {
- this(allocator);
-
- allocator.resizeArray(rep, value.length);
- value.rep.get.copy(rep.get);
- sign = value.sign;
- }
-
- /// Ditto.
- this(shared Allocator allocator) nothrow @safe @nogc
- {
- this.allocator = allocator;
- rep = RefCounted!(ubyte[])(allocator);
- }
-
/*
* Figures out the minimum amount of space this value will take
* up in bytes and resizes the internal storage. Sets the sign.
@@ -99,6 +94,7 @@ struct Integer
in
{
static assert(isIntegral!T);
+ assert(allocator !is null);
}
body
{
@@ -123,8 +119,16 @@ struct Integer
}
--size;
}
- allocator.resizeArray(rep.get, size);
-
+ if (rep.count)
+ {
+ allocator.resizeArray(rep.get, size);
+ }
+ else
+ {
+ rep = RefCounted!(ubyte[])(() @trusted {
+ return cast(ubyte[]) allocator.allocate(size);
+ }(), allocator);
+ }
/* Work backward through the int, masking off each byte (up to the
first 0 byte) and copy it into the internal representation in
big-endian format. */
@@ -146,23 +150,31 @@ struct Integer
* Returns: $(D_KEYWORD this).
*/
ref Integer opAssign(T)(in T value) nothrow @safe @nogc
- if (isIntegral!T)
+ if (isIntegral!T || is(T == Integer))
{
- checkAllocator();
- assignInt(value);
-
- return this;
- }
-
- /// Ditto.
- ref Integer opAssign(in Integer value) nothrow @safe @nogc
- {
- checkAllocator();
-
- allocator.resizeArray(rep, value.length);
- value.rep.get.copy(rep.get);
-
- sign = value.sign;
+ if (allocator is null)
+ {
+ allocator = defaultAllocator;
+ }
+ static if (isIntegral!T)
+ {
+ assignInt(value);
+ }
+ else
+ {
+ if (rep.count)
+ {
+ allocator.resizeArray(rep, value.length);
+ }
+ else
+ {
+ rep = RefCounted!(ubyte[])(() @trusted {
+ return cast(ubyte[]) allocator.allocate(value.length);
+ }(), allocator);
+ }
+ value.rep.get.copy(rep.get);
+ sign = value.sign;
+ }
return this;
}
@@ -368,7 +380,7 @@ struct Integer
}
body
{
- checkAllocator();
+ initialize();
static if (op == "+")
{
if (h.sign == sign)
@@ -522,7 +534,7 @@ struct Integer
}
body
{
- checkAllocator();
+ initialize();
auto divisor = Integer(h, allocator);
size_t bitSize;
@@ -654,7 +666,7 @@ struct Integer
Integer opUnary(string op)() nothrow @safe @nogc
if ((op == "+") || (op == "-") || (op == "~"))
{
- checkAllocator();
+ initialize();
auto h = Integer(this, allocator);
static if (op == "-")
{
@@ -748,7 +760,7 @@ struct Integer
}
body
{
- checkAllocator();
+ initialize();
static if (op == "++")
{
@@ -820,12 +832,16 @@ struct Integer
assert(h.rep[0] == 0x01);
}
- private void checkAllocator() nothrow @safe @nogc
+ private void initialize() nothrow @safe @nogc
{
if (allocator is null)
{
allocator = defaultAllocator;
}
+ if (!rep.count)
+ {
+ rep = allocator.refCounted!(ubyte[])(0);
+ }
}
/**
@@ -895,7 +911,7 @@ struct Integer
{
immutable step = n / 8;
- checkAllocator();
+ initialize();
if (step >= rep.length)
{
allocator.resizeArray(rep, 0);
@@ -976,7 +992,7 @@ struct Integer
immutable bit = n % 8;
immutable delta = 8 - bit;
- checkAllocator();
+ initialize();
if (cast(ubyte) (rep[0] >> delta))
{
allocator.resizeArray(rep, i + n / 8 + 1);
@@ -1015,7 +1031,7 @@ struct Integer
if (op == "<<" || op == ">>" || op == "+" || op == "-" || op == "/"
|| op == "*" || op == "^^" || op == "%")
{
- checkAllocator();
+ initialize();
auto ret = Integer(this, allocator);
mixin("ret " ~ op ~ "= n;");
return ret;
@@ -1037,7 +1053,7 @@ struct Integer
if (op == "+" || op == "-" || op == "/"
|| op == "*" || op == "^^" || op == "%")
{
- checkAllocator();
+ initialize();
auto ret = Integer(this, allocator);
mixin("ret " ~ op ~ "= h;");
return ret;
diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d
index 9a3a2ef..9832d74 100644
--- a/source/tanya/memory/package.d
+++ b/source/tanya/memory/package.d
@@ -11,7 +11,6 @@
module tanya.memory;
import core.exception;
-import std.algorithm.mutation;
public import std.experimental.allocator : make, makeArray, expandArray,
stateSize, shrinkArray;
import std.traits;
@@ -66,7 +65,7 @@ bool resizeArray(T)(shared Allocator allocator,
array = () @trusted { return cast(T[]) buf; }();
if (oldLength < length)
{
- array[oldLength .. $].uninitializedFill(init);
+ array[oldLength .. $] = init;
}
return true;
}
diff --git a/source/tanya/memory/types.d b/source/tanya/memory/types.d
index 1c899be..e269a7c 100644
--- a/source/tanya/memory/types.d
+++ b/source/tanya/memory/types.d
@@ -30,12 +30,13 @@ struct RefCounted(T)
{
static if (isReference!T)
{
- private T payload;
+ private alias Payload = T;
}
else
{
- private T* payload;
+ private alias Payload = T*;
}
+ private Payload payload_;
private uint counter;
@@ -48,33 +49,20 @@ struct RefCounted(T)
/**
* Takes ownership over $(D_PARAM value), setting the counter to 1.
+ * $(D_PARAM value) may be a pointer, an object or a dynamic array.
*
* Params:
* value = Value whose ownership is taken over.
* allocator = Allocator used to destroy the $(D_PARAM value) and to
* allocate/deallocate internal storage.
-
+ *
* Precondition: $(D_INLINECODE allocator !is null)
*/
- this(T value, shared Allocator allocator = defaultAllocator)
- in
- {
- assert(allocator !is null);
- }
- body
+ this(Payload value, shared Allocator allocator = defaultAllocator)
{
this(allocator);
- static if (!isReference!T)
- {
- payload = cast(T*) allocator.allocate(stateSize!T).ptr;
- move(value, *payload);
- counter = 1;
- }
- else if (value !is null)
- {
- move(value, payload);
- counter = 1;
- }
+ move(value, payload_);
+ counter = 1;
}
/// Ditto.
@@ -93,7 +81,7 @@ struct RefCounted(T)
*/
this(this) pure nothrow @safe @nogc
{
- if (isInitialized)
+ if (count)
{
++counter;
}
@@ -106,12 +94,12 @@ struct RefCounted(T)
*/
~this()
{
- if (isInitialized && !--counter)
+ if (count && !--counter)
{
static if (isReference!T)
{
- allocator.dispose(payload);
- payload = null;
+ allocator.dispose(payload_);
+ payload_ = null;
}
}
}
@@ -138,23 +126,34 @@ struct RefCounted(T)
}
static if (isReference!T)
{
- counter == 1 ? allocator.dispose(payload) : --counter;
+ if (counter > 1)
+ {
+ --counter;
+ }
+ else if (counter == 1)
+ {
+ allocator.dispose(payload_);
+ }
+ else
+ {
+ counter = 1;
+ }
}
- else if (!isInitialized)
+ else if (!count)
{
- payload = cast(T*) allocator.allocate(stateSize!T).ptr;
+ payload_ = cast(T*) allocator.allocate(stateSize!T).ptr;
counter = 1;
}
- move(rhs, get);
- return get;
+ move(rhs, payload);
+ return payload;
}
/// Ditto.
ref typeof(this) opAssign(typeof(this) rhs)
{
- swap(counter, rhs.counter);
- swap(get, rhs.get);
swap(allocator, rhs.allocator);
+ swap(counter, rhs.counter);
+ swap(payload, rhs.payload);
return this;
}
@@ -169,24 +168,27 @@ struct RefCounted(T)
*/
inout(T2) opCast(T2)() inout pure nothrow @safe @nogc
if (is(T : T2))
- in
- {
- assert(payload !is null, "Attempted to access an uninitialized reference.");
- }
- body
{
return get;
}
- ref inout(T) get() inout return pure nothrow @safe @nogc
+ /**
+ * Returns: Reference to the owned object.
+ */
+ ref inout(T) get() inout pure nothrow @safe @nogc
+ in
+ {
+ assert(counter, "Attempted to access an uninitialized reference.");
+ }
+ body
{
static if (isReference!T)
{
- return payload;
+ return payload_;
}
else
{
- return *payload;
+ return *payload_;
}
}
@@ -200,12 +202,17 @@ struct RefCounted(T)
return counter;
}
- /**
- * Returns: Whether tihs $(D_PSYMBOL RefCounted) is initialized.
- */
- @property bool isInitialized() const pure nothrow @safe @nogc
+ pragma(inline, true)
+ private ref inout(T) payload() inout return pure nothrow @safe @nogc
{
- return counter != 0;
+ static if (isReference!T)
+ {
+ return payload_;
+ }
+ else
+ {
+ return *payload_;
+ }
}
alias get this;
@@ -248,9 +255,9 @@ unittest
this(ref ubyte[] member)
{
- assert(!this.member.isInitialized);
+ assert(!this.member.count);
this.member = member;
- assert(this.member.isInitialized);
+ assert(this.member.count);
}
}
@@ -291,17 +298,20 @@ private unittest
assert(destroyed == 1);
RefCounted!int rc;
+ assert(rc.count == 0);
rc = 8;
+ assert(rc.count == 1);
}
private unittest
{
- auto rc = RefCounted!int(5);
+ auto val = defaultAllocator.make!int(5);
+ auto rc = RefCounted!int(val);
- static assert(is(typeof(rc.payload) == int*));
+ static assert(is(typeof(rc.payload_) == int*));
static assert(is(typeof(cast(int) rc) == int));
- static assert(is(typeof(RefCounted!(int*).payload) == int*));
+ static assert(is(typeof(RefCounted!(int*).payload_) == int*));
static assert(is(typeof(cast(A) (RefCounted!A())) == A));
static assert(is(typeof(cast(Object) (RefCounted!A())) == Object));
@@ -326,7 +336,11 @@ private unittest
RefCounted!T refCounted(T, A...)(shared Allocator allocator, auto ref A args)
if (!is(T == interface) && !isAbstractClass!T)
{
- static if (isReference!T)
+ static if (isDynamicArray!T)
+ {
+ return typeof(return)(allocator.makeArray!(ForeachType!T)(args), allocator);
+ }
+ else static if (isReference!T)
{
return typeof(return)(allocator.make!T(args), allocator);
}
@@ -334,7 +348,7 @@ RefCounted!T refCounted(T, A...)(shared Allocator allocator, auto ref A args)
{
auto rc = typeof(return)(allocator);
rc.counter = 1;
- rc.payload = allocator.make!T(args);
+ rc.payload_ = allocator.make!T(args);
return rc;
}
}
@@ -378,6 +392,6 @@ private unittest
}
{
auto rc = defaultAllocator.refCounted!E();
- assert(rc.isInitialized);
+ assert(rc.count);
}
}