From 1e46109e50d9b283eaead24aa13fb5216f18866d Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Mon, 29 Oct 2018 11:14:33 +0100 Subject: [PATCH] algorithm.mutation.destroyAll: New Fix #71. --- source/tanya/algorithm/mutation.d | 46 +++++++++++++++++++++++++++++++ source/tanya/container/array.d | 20 ++++---------- source/tanya/memory/package.d | 8 +----- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d index 49539d1..99ba239 100644 --- a/source/tanya/algorithm/mutation.d +++ b/source/tanya/algorithm/mutation.d @@ -561,3 +561,49 @@ if (isInputRange!Range && hasLvalueElements!Range) NonCopyable[] nonCopyable; initializeAll(nonCopyable); } + +/** + * Destroys all elements in the $(D_PARAM range). + * + * This function has effect only if the element type of $(D_PARAM Range) has + * an elaborate destructor, i.e. it is a $(D_PSYMBOL struct) with an explicit + * or generated by the compiler destructor. + * + * Params: + * Range = Input range type. + * range = Input range. + */ +void destroyAll(Range)(Range range) +if (isInputRange!Range && hasLvalueElements!Range) +{ + static if (hasElaborateDestructor!(ElementType!Range)) + { + foreach (ref e; range) + { + destroy(e); + } + } +} + +/// +@nogc nothrow pure @trusted unittest +{ + static struct WithDtor + { + private size_t* counter; + ~this() @nogc nothrow pure + { + if (this.counter !is null) + { + ++(*this.counter); + } + } + } + + size_t counter; + WithDtor[2] withDtor = [WithDtor(&counter), WithDtor(&counter)]; + + destroyAll(withDtor[]); + + assert(counter == 2); +} diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d index 57ea482..e0556dd 100644 --- a/source/tanya/container/array.d +++ b/source/tanya/container/array.d @@ -414,27 +414,19 @@ struct Array(T) */ @property void length(size_t len) @trusted { - if (len == length) - { - return; - } - else if (len > length) + if (len > length) { reserve(len); initializeAll(this.data[length_ .. len]); } else { - static if (hasElaborateDestructor!T) - { - const T* end = this.data + length_ - 1; - for (T* e = this.data + len; e != end; ++e) - { - destroy(*e); - } - } + destroyAll(this.data[len .. this.length_]); + } + if (len != length) + { + length_ = len; } - length_ = len; } /// diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d index f0a1c0d..77dc388 100644 --- a/source/tanya/memory/package.d +++ b/source/tanya/memory/package.d @@ -341,13 +341,7 @@ if (isPolymorphicType!T) package(tanya) void[] finalize(T)(ref T[] p) { - static if (hasElaborateDestructor!(typeof(p[0]))) - { - foreach (ref e; p) - { - destroy(e); - } - } + destroyAll(p); return p; }