Skip to content

Commit

Permalink
Merge pull request #5515 from dukc/fiberRangeInterface
Browse files Browse the repository at this point in the history
Generator implements InputRange interface
merged-on-behalf-of: Jack Stouffer <[email protected]>
  • Loading branch information
dlang-bot authored Jul 1, 2017
2 parents 404c4c2 + 942da35 commit 83ae83c
Showing 1 changed file with 76 additions and 2 deletions.
78 changes: 76 additions & 2 deletions std/concurrency.d
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import core.sync.condition;
import core.sync.mutex;
import core.thread;
import std.range.primitives;
import std.range.interfaces : InputRange;
import std.traits;

private
Expand Down Expand Up @@ -1496,7 +1497,8 @@ private interface IsGenerator {}
* }
* ---
*/
class Generator(T) : Fiber, IsGenerator
class Generator(T) :
Fiber, IsGenerator, InputRange!T
{
/**
* Initializes a generator object which is associated with a static
Expand Down Expand Up @@ -1585,13 +1587,52 @@ class Generator(T) : Fiber, IsGenerator
}

/**
* 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 executing a
* copy contructor. Will not compile for element types defining a
* postblit, because Generator does not return by reference.
*/
final T moveFront()
{
static if (!hasElaborateCopyConstructor!T)
{
return front;
}
else
{
static assert(0,
"Fiber front is always rvalue and thus cannot be moved since 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;
}
Expand Down Expand Up @@ -1668,6 +1709,39 @@ 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);

size_t[2] counter = [0, 0];
foreach (i, unused; myIota) counter[] += [1, i];

assert(myIota.empty);
assert(counter == [7, 21]);
}

private
{
Expand Down

0 comments on commit 83ae83c

Please sign in to comment.