summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-03-19 06:10:27 +0100
committerEugen Wissner <belka@caraus.de>2017-03-19 06:10:27 +0100
commitb90c56395cb8a3c4cabde4acc7654dd9ceffc87e (patch)
tree4370cf4219e64eeec68a1bb8cc7de7cf75b1f9c9
parentd0ada39fa752abf7f8ad24e1353d03ea5d296e82 (diff)
downloadtanya-b90c56395cb8a3c4cabde4acc7654dd9ceffc87e.tar.gz
Remove resizeArray alias
-rw-r--r--source/tanya/math/random.d532
-rw-r--r--source/tanya/memory/package.d379
2 files changed, 452 insertions, 459 deletions
diff --git a/source/tanya/math/random.d b/source/tanya/math/random.d
index e58d209..76295f7 100644
--- a/source/tanya/math/random.d
+++ b/source/tanya/math/random.d
@@ -8,8 +8,8 @@
* Copyright: Eugene Wissner 2016.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
- * Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner)
- */
+ * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
+ */
module tanya.math.random;
import std.digest.sha;
@@ -27,20 +27,20 @@ enum maxGather = 128;
*/
class EntropyException : Exception
{
- /**
- * Params:
- * msg = Message to output.
- * 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,
- string file = __FILE__,
- size_t line = __LINE__,
- Throwable next = null) pure @safe nothrow const @nogc
- {
- super(msg, file, line, next);
- }
+ /**
+ * Params:
+ * msg = Message to output.
+ * 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,
+ string file = __FILE__,
+ size_t line = __LINE__,
+ Throwable next = null) pure @safe nothrow const @nogc
+ {
+ super(msg, file, line, next);
+ }
}
/**
@@ -48,103 +48,103 @@ class EntropyException : Exception
*/
abstract class EntropySource
{
- /// Amount of already generated entropy.
- protected ushort size_;
-
- /**
- * Returns: Minimum bytes required from the entropy source.
- */
- @property immutable(ubyte) threshold() const @safe pure nothrow;
-
- /**
- * Returns: Whether this entropy source is strong.
- */
- @property immutable(bool) strong() const @safe pure nothrow;
-
- /**
- * Returns: Amount of already generated entropy.
- */
- @property ushort size() const @safe pure nothrow
- {
- return size_;
- }
-
- /**
- * Params:
- * size = Amount of already generated entropy. Cannot be smaller than the
- * already set value.
- */
- @property void size(ushort size) @safe pure nothrow
- {
- size_ = size;
- }
-
- /**
- * Poll the entropy source.
- *
- * Params:
- * output = Buffer to save the generate random sequence (the method will
- * to fill the buffer).
- *
- * Returns: Number of bytes that were copied to the $(D_PARAM output)
- * or $(D_PSYMBOL Nullable!ubyte.init) on error.
- */
- Nullable!ubyte poll(out ubyte[maxGather] output);
+ /// Amount of already generated entropy.
+ protected ushort size_;
+
+ /**
+ * Returns: Minimum bytes required from the entropy source.
+ */
+ @property immutable(ubyte) threshold() const @safe pure nothrow;
+
+ /**
+ * Returns: Whether this entropy source is strong.
+ */
+ @property immutable(bool) strong() const @safe pure nothrow;
+
+ /**
+ * Returns: Amount of already generated entropy.
+ */
+ @property ushort size() const @safe pure nothrow
+ {
+ return size_;
+ }
+
+ /**
+ * Params:
+ * size = Amount of already generated entropy. Cannot be smaller than the
+ * already set value.
+ */
+ @property void size(ushort size) @safe pure nothrow
+ {
+ size_ = size;
+ }
+
+ /**
+ * Poll the entropy source.
+ *
+ * Params:
+ * output = Buffer to save the generate random sequence (the method will
+ * to fill the buffer).
+ *
+ * Returns: Number of bytes that were copied to the $(D_PARAM output)
+ * or $(D_PSYMBOL Nullable!ubyte.init) on error.
+ */
+ Nullable!ubyte poll(out ubyte[maxGather] output);
}
version (linux)
{
- extern (C) long syscall(long number, ...) nothrow;
-
- /**
- * Uses getrandom system call.
- */
- class PlatformEntropySource : EntropySource
- {
- /**
- * Returns: Minimum bytes required from the entropy source.
- */
- override @property immutable(ubyte) threshold() const @safe pure nothrow
- {
- return 32;
- }
-
- /**
- * Returns: Whether this entropy source is strong.
- */
- override @property immutable(bool) strong() const @safe pure nothrow
- {
- return true;
- }
-
- /**
- * Poll the entropy source.
- *
- * Params:
- * output = Buffer to save the generate random sequence (the method will
- * to fill the buffer).
- *
- * Returns: Number of bytes that were copied to the $(D_PARAM output)
- * or $(D_PSYMBOL Nullable!ubyte.init) on error.
- */
- override Nullable!ubyte poll(out ubyte[maxGather] output) nothrow
- out (length)
- {
- assert(length <= maxGather);
- }
- body
- {
- // int getrandom(void *buf, size_t buflen, unsigned int flags);
- auto length = syscall(318, output.ptr, output.length, 0);
- Nullable!ubyte ret;
-
- if (length >= 0)
- {
- ret = cast(ubyte) length;
- }
- return ret;
- }
- }
+ extern (C) long syscall(long number, ...) nothrow;
+
+ /**
+ * Uses getrandom system call.
+ */
+ class PlatformEntropySource : EntropySource
+ {
+ /**
+ * Returns: Minimum bytes required from the entropy source.
+ */
+ override @property immutable(ubyte) threshold() const @safe pure nothrow
+ {
+ return 32;
+ }
+
+ /**
+ * Returns: Whether this entropy source is strong.
+ */
+ override @property immutable(bool) strong() const @safe pure nothrow
+ {
+ return true;
+ }
+
+ /**
+ * Poll the entropy source.
+ *
+ * Params:
+ * output = Buffer to save the generate random sequence (the method will
+ * to fill the buffer).
+ *
+ * Returns: Number of bytes that were copied to the $(D_PARAM output)
+ * or $(D_PSYMBOL Nullable!ubyte.init) on error.
+ */
+ override Nullable!ubyte poll(out ubyte[maxGather] output) nothrow
+ out (length)
+ {
+ assert(length <= maxGather);
+ }
+ body
+ {
+ // int getrandom(void *buf, size_t buflen, unsigned int flags);
+ auto length = syscall(318, output.ptr, output.length, 0);
+ Nullable!ubyte ret;
+
+ if (length >= 0)
+ {
+ ret = cast(ubyte) length;
+ }
+ return ret;
+ }
+ }
}
/**
@@ -156,165 +156,165 @@ version (linux)
*
* output = entropy.random;
*
- * defaultAllocator.finalize(entropy);
+ * defaultAllocator.dispose(entropy);
* ---
*/
class Entropy
{
- /// Entropy sources.
- protected EntropySource[] sources;
-
- private ubyte sourceCount_;
-
- private shared Allocator allocator;
-
- /// Entropy accumulator.
- protected SHA!(maxGather * 8, 512) accumulator;
-
- /**
- * Params:
- * maxSources = Maximum amount of entropy sources can be set.
- * allocator = Allocator to allocate entropy sources available on the
- * system.
- */
- this(size_t maxSources = 20, shared Allocator allocator = defaultAllocator)
- in
- {
- assert(maxSources > 0 && maxSources <= ubyte.max);
- assert(allocator !is null);
- }
- body
- {
- allocator.resizeArray(sources, maxSources);
-
- version (linux)
- {
- this ~= allocator.make!PlatformEntropySource;
- }
- }
-
- /**
- * Returns: Amount of the registered entropy sources.
- */
- @property ubyte sourceCount() const @safe pure nothrow
- {
- return sourceCount_;
- }
-
- /**
- * Add an entropy source.
- *
- * Params:
- * source = Entropy source.
- *
- * Returns: $(D_PSYMBOL this).
- *
- * See_Also:
- * $(D_PSYMBOL EntropySource)
- */
- Entropy opOpAssign(string Op)(EntropySource source) @safe pure nothrow
- if (Op == "~")
- in
- {
- assert(sourceCount_ <= sources.length);
- }
- body
- {
- sources[sourceCount_++] = source;
- return this;
- }
-
- /**
- * Returns: Generated random sequence.
- *
- * Throws: $(D_PSYMBOL EntropyException) if no strong entropy source was
- * registered or it failed.
- */
- @property ubyte[blockSize] random()
- in
- {
- assert(sourceCount_ > 0, "No entropy sources defined.");
- }
- body
- {
- bool haveStrong;
- ushort done;
- ubyte[blockSize] output;
-
- do
- {
- ubyte[maxGather] buffer;
-
- // Run through our entropy sources
- for (ubyte i; i < sourceCount; ++i)
- {
- auto outputLength = sources[i].poll(buffer);
-
- if (!outputLength.isNull)
- {
- if (outputLength > 0)
- {
- update(i, buffer, outputLength);
- sources[i].size = cast(ushort) (sources[i].size + outputLength);
- }
- if (sources[i].size < sources[i].threshold)
- {
- continue;
- }
- else if (sources[i].strong)
- {
- haveStrong = true;
- }
- }
- done = 257;
- }
- }
- while (++done < 256);
-
- if (!haveStrong)
- {
- throw allocator.make!EntropyException("No strong entropy source defined.");
- }
-
- output = accumulator.finish();
-
- // Reset accumulator and counters and recycle existing entropy
- accumulator.start();
-
- // Perform second SHA-512 on entropy
- output = sha512Of(output);
-
- for (ubyte i = 0; i < sourceCount; ++i)
- {
- sources[i].size = 0;
- }
- return output;
- }
-
- /**
- * Update entropy accumulator.
- *
- * Params:
- * sourceId = Entropy source index in $(D_PSYMBOL sources).
- * data = Data got from the entropy source.
- * length = Length of the received data.
- */
- protected void update(in ubyte sourceId,
- ref ubyte[maxGather] data,
- ubyte length) @safe pure nothrow
- {
- ubyte[2] header;
-
- if (length > blockSize)
- {
- data[0..64] = sha512Of(data);
- length = blockSize;
- }
-
- header[0] = sourceId;
- header[1] = length;
-
- accumulator.put(header);
- accumulator.put(data[0..length]);
- }
+ /// Entropy sources.
+ protected EntropySource[] sources;
+
+ private ubyte sourceCount_;
+
+ private shared Allocator allocator;
+
+ /// Entropy accumulator.
+ protected SHA!(maxGather * 8, 512) accumulator;
+
+ /**
+ * Params:
+ * maxSources = Maximum amount of entropy sources can be set.
+ * allocator = Allocator to allocate entropy sources available on the
+ * system.
+ */
+ this(size_t maxSources = 20, shared Allocator allocator = defaultAllocator)
+ in
+ {
+ assert(maxSources > 0 && maxSources <= ubyte.max);
+ assert(allocator !is null);
+ }
+ body
+ {
+ allocator.resize(sources, maxSources);
+
+ version (linux)
+ {
+ this ~= allocator.make!PlatformEntropySource;
+ }
+ }
+
+ /**
+ * Returns: Amount of the registered entropy sources.
+ */
+ @property ubyte sourceCount() const @safe pure nothrow
+ {
+ return sourceCount_;
+ }
+
+ /**
+ * Add an entropy source.
+ *
+ * Params:
+ * source = Entropy source.
+ *
+ * Returns: $(D_PSYMBOL this).
+ *
+ * See_Also:
+ * $(D_PSYMBOL EntropySource)
+ */
+ Entropy opOpAssign(string Op)(EntropySource source) @safe pure nothrow
+ if (Op == "~")
+ in
+ {
+ assert(sourceCount_ <= sources.length);
+ }
+ body
+ {
+ sources[sourceCount_++] = source;
+ return this;
+ }
+
+ /**
+ * Returns: Generated random sequence.
+ *
+ * Throws: $(D_PSYMBOL EntropyException) if no strong entropy source was
+ * registered or it failed.
+ */
+ @property ubyte[blockSize] random()
+ in
+ {
+ assert(sourceCount_ > 0, "No entropy sources defined.");
+ }
+ body
+ {
+ bool haveStrong;
+ ushort done;
+ ubyte[blockSize] output;
+
+ do
+ {
+ ubyte[maxGather] buffer;
+
+ // Run through our entropy sources
+ for (ubyte i; i < sourceCount; ++i)
+ {
+ auto outputLength = sources[i].poll(buffer);
+
+ if (!outputLength.isNull)
+ {
+ if (outputLength > 0)
+ {
+ update(i, buffer, outputLength);
+ sources[i].size = cast(ushort) (sources[i].size + outputLength);
+ }
+ if (sources[i].size < sources[i].threshold)
+ {
+ continue;
+ }
+ else if (sources[i].strong)
+ {
+ haveStrong = true;
+ }
+ }
+ done = 257;
+ }
+ }
+ while (++done < 256);
+
+ if (!haveStrong)
+ {
+ throw allocator.make!EntropyException("No strong entropy source defined.");
+ }
+
+ output = accumulator.finish();
+
+ // Reset accumulator and counters and recycle existing entropy
+ accumulator.start();
+
+ // Perform second SHA-512 on entropy
+ output = sha512Of(output);
+
+ for (ubyte i = 0; i < sourceCount; ++i)
+ {
+ sources[i].size = 0;
+ }
+ return output;
+ }
+
+ /**
+ * Update entropy accumulator.
+ *
+ * Params:
+ * sourceId = Entropy source index in $(D_PSYMBOL sources).
+ * data = Data got from the entropy source.
+ * length = Length of the received data.
+ */
+ protected void update(in ubyte sourceId,
+ ref ubyte[maxGather] data,
+ ubyte length) @safe pure nothrow
+ {
+ ubyte[2] header;
+
+ if (length > blockSize)
+ {
+ data[0..64] = sha512Of(data);
+ length = blockSize;
+ }
+
+ header[0] = sourceId;
+ header[1] = length;
+
+ accumulator.put(header);
+ accumulator.put(data[0..length]);
+ }
}
diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d
index 9ecb45b..da53ecf 100644
--- a/source/tanya/memory/package.d
+++ b/source/tanya/memory/package.d
@@ -23,59 +23,61 @@ public import tanya.memory.allocator;
*/
mixin template DefaultAllocator()
{
- /// Allocator.
- protected shared Allocator allocator_;
+ /// Allocator.
+ protected shared Allocator allocator_;
- /**
- * Params:
- * allocator = The allocator should be used.
- */
- this(shared Allocator allocator)
- in
- {
- assert(allocator !is null);
- }
- body
- {
- this.allocator_ = allocator;
- }
+ /**
+ * Params:
+ * allocator = The allocator should be used.
+ *
+ * Precondition: $(D_INLINECODE allocator_ !is null)
+ */
+ this(shared Allocator allocator)
+ in
+ {
+ assert(allocator !is null);
+ }
+ body
+ {
+ this.allocator_ = allocator;
+ }
- /**
- * This property checks if the allocator was set in the constructor
- * and sets it to the default one, if not.
- *
- * Returns: Used allocator.
- *
- * Postcondition: $(D_INLINECODE allocator_ !is null)
- */
- protected @property shared(Allocator) allocator() nothrow @safe @nogc
- out (allocator)
- {
- assert(allocator !is null);
- }
- body
- {
- if (allocator_ is null)
- {
- allocator_ = defaultAllocator;
- }
- return allocator_;
- }
+ /**
+ * This property checks if the allocator was set in the constructor
+ * and sets it to the default one, if not.
+ *
+ * Returns: Used allocator.
+ *
+ * Postcondition: $(D_INLINECODE allocator !is null)
+ */
+ protected @property shared(Allocator) allocator() nothrow @safe @nogc
+ out (allocator)
+ {
+ assert(allocator !is null);
+ }
+ body
+ {
+ if (allocator_ is null)
+ {
+ allocator_ = defaultAllocator;
+ }
+ return allocator_;
+ }
- /// Ditto.
- @property shared(Allocator) allocator() const nothrow @trusted @nogc
- out (allocator)
- {
- assert(allocator !is null);
- }
- body
- {
- if (allocator_ is null)
- {
- return defaultAllocator;
- }
- return cast(shared Allocator) allocator_;
- }
+ /// Ditto.
+ @property shared(Allocator) allocator() const nothrow @trusted @nogc
+ out (allocator)
+ {
+ assert(allocator !is null);
+ }
+ body
+ {
+ if (allocator_ is null)
+ {
+ return defaultAllocator;
+ }
+ return cast(shared Allocator) allocator_;
+ }
}
// From druntime
@@ -85,28 +87,28 @@ shared Allocator allocator;
shared static this() nothrow @trusted @nogc
{
- import tanya.memory.mmappool;
- allocator = MmapPool.instance;
+ import tanya.memory.mmappool;
+ allocator = MmapPool.instance;
}
@property ref shared(Allocator) defaultAllocator() nothrow @safe @nogc
out (allocator)
{
- assert(allocator !is null);
+ assert(allocator !is null);
}
body
{
- return allocator;
+ return allocator;
}
@property void defaultAllocator(shared(Allocator) allocator) nothrow @safe @nogc
in
{
- assert(allocator !is null);
+ assert(allocator !is null);
}
body
{
- .allocator = allocator;
+ .allocator = allocator;
}
/**
@@ -114,101 +116,92 @@ body
* object of type $(D_PARAM T).
*
* Params:
- * T = Object type.
+ * T = Object type.
*/
template stateSize(T)
{
- static if (is(T == class) || is(T == interface))
- {
- enum stateSize = __traits(classInstanceSize, T);
- }
- else
- {
- enum stateSize = T.sizeof;
- }
+ static if (is(T == class) || is(T == interface))
+ {
+ enum stateSize = __traits(classInstanceSize, T);
+ }
+ else
+ {
+ enum stateSize = T.sizeof;
+ }
}
/**
* Params:
- * size = Raw size.
- * alignment = Alignment.
+ * size = Raw size.
+ * alignment = Alignment.
*
* Returns: Aligned size.
*/
size_t alignedSize(in size_t size, in size_t alignment = 8) pure nothrow @safe @nogc
{
- return (size - 1) / alignment * alignment + alignment;
+ return (size - 1) / alignment * alignment + alignment;
}
/**
* Internal function used to create, resize or destroy a dynamic array. It
- * throws $(D_PSYMBOL OutOfMemoryError) if $(D_PARAM Throws) is set. The new
+ * may throw $(D_PSYMBOL OutOfMemoryError). The new
* allocated part of the array is initialized only if $(D_PARAM Init)
* is set. This function can be trusted only in the data structures that
* can ensure that the array is allocated/rellocated/deallocated with the
* same allocator.
*
* Params:
- * T = Element type of the array being created.
- * Init = If should be initialized.
- * Throws = If $(D_PSYMBOL OutOfMemoryError) should be throwsn.
- * allocator = The allocator used for getting memory.
- * array = A reference to the array being changed.
- * length = New array length.
+ * T = Element type of the array being created.
+ * Init = If should be initialized.
+ * allocator = The allocator used for getting memory.
+ * array = A reference to the array being changed.
+ * length = New array length.
*
- * Returns: $(D_KEYWORD true) upon success, $(D_KEYWORD false) if memory could
- * not be reallocated. In the latter
+ * Returns: $(D_PARAM array).
*/
-package(tanya) bool resize(T,
- bool Init = true,
- bool Throws = true)
- (shared Allocator allocator,
- ref T[] array,
- in size_t length) @trusted
+package(tanya) T[] resize(T,
+ bool Init = true)
+ (shared Allocator allocator,
+ auto ref T[] array,
+ const size_t length) @trusted
{
- void[] buf = array;
- static if (Init)
- {
- immutable oldLength = array.length;
- }
- if (!allocator.reallocate(buf, length * T.sizeof))
- {
- static if (Throws)
- {
- onOutOfMemoryError;
- }
- return false;
- }
- // Casting from void[] is unsafe, but we know we cast to the original type.
- array = cast(T[]) buf;
+ void[] buf = array;
+ static if (Init)
+ {
+ const oldLength = array.length;
+ }
+ 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;
- static if (Init)
- {
- if (oldLength < length)
- {
- array[oldLength .. $] = T.init;
- }
- }
- return true;
+ static if (Init)
+ {
+ if (oldLength < length)
+ {
+ array[oldLength .. $] = T.init;
+ }
+ }
+ return array;
}
-package(tanya) alias resizeArray = resize;
-///
-unittest
+private unittest
{
- int[] p;
+ int[] p;
- defaultAllocator.resizeArray(p, 20);
- assert(p.length == 20);
+ p = defaultAllocator.resize(p, 20);
+ assert(p.length == 20);
- defaultAllocator.resizeArray(p, 30);
- assert(p.length == 30);
+ p = defaultAllocator.resize(p, 30);
+ assert(p.length == 30);
- defaultAllocator.resizeArray(p, 10);
- assert(p.length == 10);
+ p = defaultAllocator.resize(p, 10);
+ assert(p.length == 10);
- defaultAllocator.resizeArray(p, 0);
- assert(p is null);
+ p = defaultAllocator.resize(p, 0);
+ assert(p is null);
}
/**
@@ -217,101 +210,101 @@ unittest
* allocator.
*
* Params:
- * T = Type of $(D_PARAM p).
- * allocator = Allocator the $(D_PARAM p) was allocated with.
- * p = Object or array to be destroyed.
+ * T = Type of $(D_PARAM p).
+ * allocator = Allocator the $(D_PARAM p) was allocated with.
+ * p = Object or array to be destroyed.
*/
void dispose(T)(shared Allocator allocator, auto ref T* p)
{
- static if (hasElaborateDestructor!T)
- {
- destroy(*p);
- }
- () @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }();
- p = null;
+ static if (hasElaborateDestructor!T)
+ {
+ destroy(*p);
+ }
+ () @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }();
+ p = null;
}
/// Ditto.
void dispose(T)(shared Allocator allocator, auto ref T p)
- if (is(T == class) || is(T == interface))
+ if (is(T == class) || is(T == interface))
{
- if (p is null)
- {
- return;
- }
- static if (is(T == interface))
- {
- version(Windows)
- {
- import core.sys.windows.unknwn : IUnknown;
- static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in "
- ~ __PRETTY_FUNCTION__);
- }
- auto ob = cast(Object) p;
- }
- else
- {
- alias ob = p;
- }
- auto ptr = cast(void *) ob;
+ if (p is null)
+ {
+ return;
+ }
+ static if (is(T == interface))
+ {
+ version(Windows)
+ {
+ import core.sys.windows.unknwn : IUnknown;
+ static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in "
+ ~ __PRETTY_FUNCTION__);
+ }
+ auto ob = cast(Object) p;
+ }
+ else
+ {
+ alias ob = p;
+ }
+ auto ptr = cast(void *) ob;
- auto support = ptr[0 .. typeid(ob).initializer.length];
- scope (success)
- {
- () @trusted { allocator.deallocate(support); }();
- p = null;
- }
+ auto support = ptr[0 .. typeid(ob).initializer.length];
+ scope (success)
+ {
+ () @trusted { allocator.deallocate(support); }();
+ p = null;
+ }
- auto ppv = cast(void**) ptr;
- if (!*ppv)
- {
- return;
- }
- auto pc = cast(ClassInfo*) *ppv;
- scope (exit)
- {
- *ppv = null;
- }
+ auto ppv = cast(void**) ptr;
+ if (!*ppv)
+ {
+ return;
+ }
+ auto pc = cast(ClassInfo*) *ppv;
+ scope (exit)
+ {
+ *ppv = null;
+ }
- auto c = *pc;
- do
- {
- // Assume the destructor is @nogc. Leave it nothrow since the destructor
- // shouldn't throw and if it does, it is an error anyway.
- if (c.destructor)
- {
- (cast(void function (Object) nothrow @safe @nogc) c.destructor)(ob);
- }
- }
- while ((c = c.base) !is null);
+ auto c = *pc;
+ do
+ {
+ // Assume the destructor is @nogc. Leave it nothrow since the destructor
+ // shouldn't throw and if it does, it is an error anyway.
+ if (c.destructor)
+ {
+ (cast(void function (Object) nothrow @safe @nogc) c.destructor)(ob);
+ }
+ }
+ while ((c = c.base) !is null);
- if (ppv[1]) // if monitor is not null
- {
- _d_monitordelete(cast(Object) ptr, true);
- }
+ if (ppv[1]) // if monitor is not null
+ {
+ _d_monitordelete(cast(Object) ptr, true);
+ }
}
/// Ditto.
void dispose(T)(shared Allocator allocator, auto ref T[] p)
{
- static if (hasElaborateDestructor!(typeof(p[0])))
- {
- import std.algorithm.iteration;
- p.each!(e => destroy(e));
- }
- () @trusted { allocator.deallocate(p); }();
- p = null;
+ static if (hasElaborateDestructor!(typeof(p[0])))
+ {
+ import std.algorithm.iteration;
+ p.each!(e => destroy(e));
+ }
+ () @trusted { allocator.deallocate(p); }();
+ p = null;
}
unittest
{
- struct S
- {
- ~this()
- {
- }
- }
- auto p = cast(S[]) defaultAllocator.allocate(S.sizeof);
+ struct S
+ {
+ ~this()
+ {
+ }
+ }
+ auto p = cast(S[]) defaultAllocator.allocate(S.sizeof);
- defaultAllocator.dispose(p);
+ defaultAllocator.dispose(p);
}