Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

So the goal of futures is to deal with inversion of control.

The code you want to write is something like:

  fn f( filename ) {
    val someUrl = computeTheUrl();
    val data = await http.get( someUrl );
    val processedData = process(Data);
    await filesystem.writeFile( filename, processedData );
  }
(I'm marking "potentially blocking" calls with "await" here)

But the code you want to run is an event loop:

  while( program_is_running() ) {
      poll_io()
      poll_network()
      run_ready_tasks()
  }
So can you do to let you write f()? You need to invert the control between run_ready_tasks() and f(). And you need to do so in a way that allows f() to both do network io, disk io, and other blocking tasks.

You're right that you can use a green thread per task to solve this problem, and "await" is then just a function that switches context to the scheduler. For various reasons, the Rust community decided that green threads were too heavy of an abstraction, and instead the compiler generates state machines (which are, in some ways, equivalent to green threads if you squint hard enough).

> if a future is inert, how can it ever detect that it is ready to make progress and call wake?

The future doesn't. When the future makes a blocking call, it needs to push its waker into some data structure handled by the top level event loop / scheduler. And then the job of the waker is to understand how to push the task back into the ready queue when whatever was being waited on completes.

The complications in Rust's design is due to their goal of making it so those compiler-generated-state-machines can be used by a library runtime -- to not require a particular standard library.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: