From ee4778ed79dfb311c852a171f09e0bbe09612a9a Mon Sep 17 00:00:00 2001 From: dukc Date: Fri, 24 Feb 2017 23:41:14 +0200 Subject: [PATCH 1/4] Since std.concurrency.Generator is a class already, I made it to implement std.range.interfaces.InputRange without having to call inputRangeObject(). --- std/concurrency.d | 74 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/std/concurrency.d b/std/concurrency.d index 89ab8e843d9..523c7900e63 100644 --- a/std/concurrency.d +++ b/std/concurrency.d @@ -1586,8 +1586,9 @@ private interface IsGenerator {} * } * --- */ +import std.range.interfaces : InputRange; class Generator(T) : - Fiber, IsGenerator + Fiber, IsGenerator, InputRange!T { /** * Initializes a generator object which is associated with a static @@ -1682,13 +1683,54 @@ class Generator(T) : /** - * Returns the most recently generated value. + * Returns the most recently generated value by shallow copy. */ final T front() @property { return *m_value; } + /** + * Returns the most recently generated value without excuting a copy + * contructor. Will not compile for element types defining a + * postblit, because Generator does not return by reference. + */ + final T moveFront() + { + import std.algorithm, std.range; + static if (!hasElaborateCopyConstructor!T) + { + return front; + } + else + { + static assert(0, + "Fiber front is rvalue and thus cannot be moved when it defines a postblit."); + } + } + + final int opApply(scope int delegate(T) loopBody) + { + int broken; + for(; !empty; popFront()) + { + broken = loopBody(front); + if(broken) break; + } + return broken; + } + + final int opApply(scope int delegate(size_t, T) loopBody) + { + int broken; + for(size_t i; !empty; ++i, popFront()) + { + broken = loopBody(i, front); + if(broken) break; + } + return broken; + } + private: T* m_value; @@ -1724,6 +1766,7 @@ void yield(T)(T value) { import core.exception; import std.exception; + import std.range.interfaces; static void testScheduler(Scheduler s) { @@ -1765,6 +1808,7 @@ void yield(T)(T value) { tid.send(e); } + }); scheduler = null; } @@ -1772,7 +1816,33 @@ void yield(T)(T value) testScheduler(new ThreadScheduler); testScheduler(new FiberScheduler); } +/// +@system unittest +{ + import std.range; + + InputRange!int myIota = iota(10).inputRangeObject; + myIota.popFront(); + myIota.popFront(); + assert(myIota.moveFront == 2); + assert(myIota.front == 2); + myIota.popFront(); + assert(myIota.front == 3); + + //can be assigned to std.range.interfaces.InputRange directly + myIota = new Generator!int( + { + foreach(i; 0 .. 10) yield(i); + }); + + myIota.popFront(); + myIota.popFront(); + assert(myIota.moveFront == 2); + assert(myIota.front == 2); + myIota.popFront(); + assert(myIota.front == 3); +} // MessageBox Implementation From cfb25fbce2cdda84a1d0717f7735b9e4be24579c Mon Sep 17 00:00:00 2001 From: dukc Date: Mon, 27 Feb 2017 16:52:46 +0200 Subject: [PATCH 2/4] Fix for style violation. --- std/concurrency.d | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/std/concurrency.d b/std/concurrency.d index 523c7900e63..8ba89f48f11 100644 --- a/std/concurrency.d +++ b/std/concurrency.d @@ -1712,10 +1712,10 @@ class Generator(T) : final int opApply(scope int delegate(T) loopBody) { int broken; - for(; !empty; popFront()) + for (; !empty; popFront()) { broken = loopBody(front); - if(broken) break; + if (broken) break; } return broken; } @@ -1723,10 +1723,10 @@ class Generator(T) : final int opApply(scope int delegate(size_t, T) loopBody) { int broken; - for(size_t i; !empty; ++i, popFront()) + for (size_t i; !empty; ++i, popFront()) { broken = loopBody(i, front); - if(broken) break; + if (broken) break; } return broken; } @@ -1833,7 +1833,7 @@ void yield(T)(T value) //can be assigned to std.range.interfaces.InputRange directly myIota = new Generator!int( { - foreach(i; 0 .. 10) yield(i); + foreach (i; 0 .. 10) yield(i); }); myIota.popFront(); From 1f926a17028e06b38e2a964de8fedd826153762a Mon Sep 17 00:00:00 2001 From: dukc Date: Mon, 27 Feb 2017 17:06:57 +0200 Subject: [PATCH 3/4] Removed a reduntant import. Removed another useless import. One import wasn't reduntant after all... --- std/concurrency.d | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/std/concurrency.d b/std/concurrency.d index 8ba89f48f11..3a5cccb69a7 100644 --- a/std/concurrency.d +++ b/std/concurrency.d @@ -75,6 +75,7 @@ private import core.sync.mutex; import core.sync.condition; import std.range.primitives; + import std.range.interfaces; import std.traits; import std.concurrencybase; @@ -1586,7 +1587,6 @@ private interface IsGenerator {} * } * --- */ -import std.range.interfaces : InputRange; class Generator(T) : Fiber, IsGenerator, InputRange!T { @@ -1697,7 +1697,6 @@ class Generator(T) : */ final T moveFront() { - import std.algorithm, std.range; static if (!hasElaborateCopyConstructor!T) { return front; From 49bd11b528443a67f322dd83c278181788e1ff6e Mon Sep 17 00:00:00 2001 From: dukc Date: Wed, 1 Mar 2017 19:51:54 +0200 Subject: [PATCH 4/4] Unittest now covers indexed foreach. --- std/concurrency.d | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/std/concurrency.d b/std/concurrency.d index 3a5cccb69a7..f7b5a587cfa 100644 --- a/std/concurrency.d +++ b/std/concurrency.d @@ -1841,6 +1841,12 @@ void yield(T)(T value) assert(myIota.front == 2); myIota.popFront(); assert(myIota.front == 3); + + size_t[2] counter = [0, 0]; + foreach (i, unused; myIota) counter[] += [1, i]; + + assert(myIota.empty); + assert(counter == [7, 21]); } // MessageBox Implementation