CarryingFiber

A Fiber carrying a payload of type T, along with some metadata.

Used interchangeably with Fiber, but allows for casting to true CarryingFiber!T-ness to access the payload member.

Constructors

this
this(FnOrDg fnOrDg, Args args, string creator)

Constructor function merely taking a function/delegate pointer, to call when invoking this fiber (via .call()).

this
this(FnOrDg fnOrDg, T payload, Args args, string creator)

Constructor function taking a T payload to assign to its own internal this.payload, as well as a function/delegate pointer to call when invoking this fiber (via .call()).

Members

Functions

call
auto call(T payload, string caller)

Hijacks the invocation of the Fiber and injects the string name of the calling function into the caller member before calling the Fiber's own .call().

call
auto call(string caller)

Hijacks the invocation of the Fiber and injects the string name of the calling function into the caller member before calling the Fiber's own .call().

resetPayload
void resetPayload()

Resets the payload to its .init value.

state
auto state()

Safely returns the state of the fiber, taking into consideration it may have been reset.

Variables

called
uint called;

How many times this CarryingFiber has been called (via .call()).

caller
string caller;

String name of the function that last called this CarryingFiber (via .call()).

creator
string creator;

String name of the function that created this CarryingFiber.

hasExpired
bool hasExpired;

Whether or not this CarryingFiber has been called to completion and should be considered expired.

payload
T payload;

Embedded payload value in this fiber; what distinguishes it from plain Fibers.

Parameters

T

Type to embed into the class as the type of CarryingFiber.payload.

Examples

void dg()
{
    auto fiber = cast(CarryingFiber!bool)Fiber.getThis();
    assert(fiber !is null);  // Correct cast

    assert(fiber.payload);
    Fiber.yield();
    assert(!fiber.payload);
}

auto fiber = new CarryingFiber!bool(&dg, true, BufferSize.fiberStack);
assert(fiber.called == 0);
fiber.call();
assert(fiber.called == 1);
fiber.payload = false;
fiber.call();
1 import std.conv : to;
2 
3 static struct Payload
4 {
5     string s = "Hello";
6     size_t i = 42;
7 
8     static auto getCompileTimeRandomPayload()
9     {
10         enum randomString = __TIMESTAMP__;
11         return Payload(randomString, hashOf(randomString));
12     }
13 }
14 
15 static auto creatorTest(void delegate() dg)
16 {
17     import kameloso.constants : BufferSize;
18 
19     auto fiber = new CarryingFiber!Payload
20         (dg,
21         Payload.getCompileTimeRandomPayload(),
22         BufferSize.fiberStack);
23     assert((fiber.called == 0), fiber.called.to!string);
24     return fiber;
25 }
26 
27 static void callerTest1(CarryingFiber!Payload fiber)
28 {
29     immutable payload = Payload.getCompileTimeRandomPayload();
30 
31     assert((fiber.payload.s == payload.s), fiber.payload.s);
32     assert((fiber.payload.i == payload.i), fiber.payload.i.to!string);
33     fiber.call();
34     assert((fiber.payload.s == Payload.init.s), fiber.payload.s);
35     assert((fiber.payload.i == Payload.init.i), fiber.payload.i.to!string);
36 }
37 
38 static void callerTest2(CarryingFiber!Payload fiber)
39 {
40     fiber.call();
41 }
42 
43 void dg()
44 {
45     auto thisFiber = cast(CarryingFiber!Payload)Fiber.getThis();
46     assert(thisFiber, "Incorrectly cast fiber: " ~ typeof(thisFiber).stringof);
47 
48     // __FUNCTION__ will be something like "kameloso.thread.__unittest_L577_C1.dg"
49     enum expectedFunction = __FUNCTION__[0..$-2] ~ "dg";
50 
51     static if (__FUNCTION__ == expectedFunction)
52     {
53         enum expectedCreator = __FUNCTION__[0..$-2] ~ "creatorTest";
54         enum expectedCaller1 = __FUNCTION__[0..$-2] ~ "callerTest1";
55         enum expectedCaller2 = __FUNCTION__[0..$-2] ~ "callerTest2";
56 
57         // First state
58         assert((thisFiber.creator == expectedCreator), thisFiber.creator);
59         assert((thisFiber.caller == expectedCaller1), thisFiber.caller);
60         assert((thisFiber.called == 1), thisFiber.called.to!string);
61         thisFiber.resetPayload();
62         Fiber.yield();
63 
64         // Second state
65         assert((thisFiber.caller == expectedCaller2), thisFiber.caller);
66         assert((thisFiber.called == 2), thisFiber.called.to!string);
67     }
68     else
69     {
70         enum message = "Bad logic slicing function names in `CarryingFiber` unit test; " ~
71             "please report this as a bug. (Was there a change in the compiler?)";
72         pragma(msg, message);
73 
74         // Yield once so the tests still pass
75         Fiber.yield();
76     }
77 }
78 
79 auto fiber = creatorTest(&dg);
80 callerTest1(fiber);
81 callerTest2(fiber);