mirror of
https://github.com/dlang/phobos.git
synced 2025-05-07 11:37:24 +03:00
Since std.concurrency.Generator is a class already, I made it to implement
std.range.interfaces.InputRange without having to call inputRangeObject().
This commit is contained in:
parent
9f82a92b46
commit
5983bcc8de
1 changed files with 86 additions and 2 deletions
|
@ -74,6 +74,14 @@ 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;
|
||||
|
||||
template hasLocalAliasing(T...)
|
||||
{
|
||||
static if (!T.length)
|
||||
|
@ -1496,7 +1504,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
|
||||
|
@ -1585,13 +1594,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;
|
||||
}
|
||||
|
@ -1624,6 +1672,7 @@ void yield(T)(T value)
|
|||
{
|
||||
import core.exception;
|
||||
import std.exception;
|
||||
import std.range.interfaces;
|
||||
|
||||
static void testScheduler(Scheduler s)
|
||||
{
|
||||
|
@ -1661,6 +1710,7 @@ void yield(T)(T value)
|
|||
{
|
||||
tid.send(e);
|
||||
}
|
||||
|
||||
});
|
||||
scheduler = null;
|
||||
}
|
||||
|
@ -1668,7 +1718,41 @@ 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]);
|
||||
}
|
||||
|
||||
// MessageBox Implementation
|
||||
private
|
||||
{
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue