Skip to content

Commit

Permalink
Since std.concurrency.Generator is a class already, I made it to impl…
Browse files Browse the repository at this point in the history
…ement

std.range.interfaces.InputRange without having to call inputRangeObject().
  • Loading branch information
dukc committed Jun 26, 2017
1 parent 9f82a92 commit 18eeb7f
Showing 1 changed file with 87 additions and 2 deletions.
89 changes: 87 additions & 2 deletions std/concurrency.d
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ import std.traits;

private
{
import core.atomic;
import core.thread;
import core.sync.mutex;
import core.sync.condition;
import std.range.primitives;
import std.range.interfaces;
import std.traits;
import std.concurrencybase;

template hasLocalAliasing(T...)
{
static if (!T.length)
Expand Down Expand Up @@ -1496,7 +1505,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 +1595,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 excuting 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 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;
}
Expand Down Expand Up @@ -1624,6 +1673,7 @@ void yield(T)(T value)
{
import core.exception;
import std.exception;
import std.range.interfaces;

static void testScheduler(Scheduler s)
{
Expand Down Expand Up @@ -1661,14 +1711,49 @@ void yield(T)(T value)
{
tid.send(e);
}

});
scheduler = null;
}

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]);
}

// MessageBox Implementation
private
{
/*
Expand Down

0 comments on commit 18eeb7f

Please sign in to comment.