Implement async/await using Fiber

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri May 20 17:15:34 PDT 2016


On 05/20/2016 12:56 PM, Yuxuan Shui wrote:
 > On Friday, 20 May 2016 at 06:40:42 UTC, Jacob Carlborg wrote:
 >> On 2016-05-20 04:14, Yuxuan Shui wrote:
 >>
 >>> Hmm... This could work. But I'm not satisfied with this solution. What
 >>> if I have multiple yield sites in the fiber, and each have different
 >>> return types?
 >>>
 >>> Maybe I should use a Variant?
 >>
 >> I think you can view "yield" as a form of "return". If you cannot
 >> return different types from a function (without it being a template)
 >> it would be weird if you could yield different types.
 >
 > But this is yield as in coroutine, not yield as in generators. Those
 > yields doesn't return value to the caller of the fiber.
 >
 > Let's have an example:
 >
 > void func() {
 >     string a = wait_for_user_input();
 >     int b = wait_for_user_to_click_a_button();
 > }
 >
 > Those two wait()s could use yield internally to transfer execution back
 > to the caller and wait for input. But it's difficult with current dlang
 > fiber because there's no (elegant) way to pass data (preferably with
 > different types) while transferring executing to/from fibers.

Agreed. Fibers are not a language construct.

One has to do what std.concurrency.Generator does internally. In this 
case, we need another layer of function calls. (I could have used 
Generator below and I could avoid creating a fiber for each call by 
moving the fibers to module-scope.)

import core.thread;

void input_fiber(ref string input) {
     while (true) {
         input = "hello";
         Fiber.yield();
     }
}

string wait_for_user_input() {
     string input;
     auto f = new Fiber(() => input_fiber(input));
     f.call();
     return input;
}

void click_fiber(ref int button) {
     while (true) {
         button = 42;
         Fiber.yield();
     }
}

int wait_for_user_to_click_a_button() {
     int button;
     auto f = new Fiber(() => click_fiber(button));
     f.call();
     return button;
}

void func() {
     foreach (i; 0 .. 10) {
         string a = wait_for_user_input();
         assert(a == "hello");

         int b = wait_for_user_to_click_a_button();
         assert(b == 42);
     }
}

void main() {
     func();
}

Ali



More information about the Digitalmars-d-learn mailing list