Add callback based result retrieval for asyncAwaitAny.
This can be used to safely retrieve scoped data.
This commit is contained in:
parent
f3c84d497e
commit
32d360baac
|
@ -42,12 +42,22 @@ nothrow {
|
||||||
return tuple(waitable.results);
|
return tuple(waitable.results);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Waitable(alias wait, alias cancel, CB) {
|
struct Waitable(alias wait, alias cancel, CB, on_result...)
|
||||||
|
if (on_result.length <= 1)
|
||||||
|
{
|
||||||
import std.traits : ReturnType;
|
import std.traits : ReturnType;
|
||||||
|
|
||||||
alias Callback = CB;
|
alias Callback = CB;
|
||||||
|
|
||||||
ParameterTypeTuple!Callback results;
|
static if (on_result.length == 0) {
|
||||||
|
ParameterTypeTuple!Callback results;
|
||||||
|
void setResult(ref ParameterTypeTuple!Callback r) { this.results = r; }
|
||||||
|
} else {
|
||||||
|
import std.format : format;
|
||||||
|
alias PTypes = ParameterTypeTuple!Callback;
|
||||||
|
mixin(q{void setResult(%s) { on_result[0](%s); }}.format(generateParamDecls!Callback, generateParamNames!Callback));
|
||||||
|
}
|
||||||
|
|
||||||
bool cancelled;
|
bool cancelled;
|
||||||
auto waitCallback(Callback cb) nothrow { return wait(cb); }
|
auto waitCallback(Callback cb) nothrow { return wait(cb); }
|
||||||
|
|
||||||
|
@ -107,7 +117,7 @@ void asyncAwaitAny(bool interruptible, string func = __FUNCTION__, Waitables...)
|
||||||
fired[i] = true;
|
fired[i] = true;
|
||||||
any_fired = true;
|
any_fired = true;
|
||||||
static if (PTypes.length)
|
static if (PTypes.length)
|
||||||
waitables[i].results = AliasSeq!(%s);
|
waitables[i].setResult(%s);
|
||||||
if (t != Task.init) switchToTask(t);
|
if (t != Task.init) switchToTask(t);
|
||||||
}}.format(generateParamDecls!(CBDel!W), generateParamNames!(CBDel!W)));
|
}}.format(generateParamDecls!(CBDel!W), generateParamNames!(CBDel!W)));
|
||||||
callbacks[i] = cb;
|
callbacks[i] = cb;
|
||||||
|
@ -186,6 +196,12 @@ private struct ScopeGuard { @safe nothrow: void delegate() op; ~this() { if (op
|
||||||
(cb) { c++; },
|
(cb) { c++; },
|
||||||
void delegate(int) @safe nothrow
|
void delegate(int) @safe nothrow
|
||||||
) w2;
|
) w2;
|
||||||
|
Waitable!(
|
||||||
|
(cb) { c++; cb(42); },
|
||||||
|
(cb) { assert(false); },
|
||||||
|
void delegate(int) @safe nothrow,
|
||||||
|
(int n) { assert(n == 42); }
|
||||||
|
) w3;
|
||||||
|
|
||||||
asyncAwaitAny!false(w1, w2);
|
asyncAwaitAny!false(w1, w2);
|
||||||
assert(w1.results[0] == 42 && w2.results[0] == 0);
|
assert(w1.results[0] == 42 && w2.results[0] == 0);
|
||||||
|
@ -194,6 +210,9 @@ private struct ScopeGuard { @safe nothrow: void delegate() op; ~this() { if (op
|
||||||
asyncAwaitAny!false(w2, w1);
|
asyncAwaitAny!false(w2, w1);
|
||||||
assert(w1.results[0] == 42 && w2.results[0] == 0);
|
assert(w1.results[0] == 42 && w2.results[0] == 0);
|
||||||
assert(a == 2 && b == 1 && c == 1);
|
assert(a == 2 && b == 1 && c == 1);
|
||||||
|
|
||||||
|
asyncAwaitAny!false(w3);
|
||||||
|
assert(c == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string generateParamDecls(Fun)()
|
private string generateParamDecls(Fun)()
|
||||||
|
|
Loading…
Reference in a new issue