mirror of
https://github.com/dlang/phobos.git
synced 2025-05-10 14:08:32 +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
|
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...)
|
template hasLocalAliasing(T...)
|
||||||
{
|
{
|
||||||
static if (!T.length)
|
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
|
* 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
|
final T front() @property
|
||||||
{
|
{
|
||||||
return *m_value;
|
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:
|
private:
|
||||||
T* m_value;
|
T* m_value;
|
||||||
}
|
}
|
||||||
|
@ -1624,6 +1672,7 @@ void yield(T)(T value)
|
||||||
{
|
{
|
||||||
import core.exception;
|
import core.exception;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
import std.range.interfaces;
|
||||||
|
|
||||||
static void testScheduler(Scheduler s)
|
static void testScheduler(Scheduler s)
|
||||||
{
|
{
|
||||||
|
@ -1661,6 +1710,7 @@ void yield(T)(T value)
|
||||||
{
|
{
|
||||||
tid.send(e);
|
tid.send(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
scheduler = null;
|
scheduler = null;
|
||||||
}
|
}
|
||||||
|
@ -1668,7 +1718,41 @@ void yield(T)(T value)
|
||||||
testScheduler(new ThreadScheduler);
|
testScheduler(new ThreadScheduler);
|
||||||
testScheduler(new FiberScheduler);
|
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
|
private
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue