On Tuesday, 24 October 2017 at 04:26:42 UTC, Adam Wilson wrote:
On 10/23/17 17:27, flamencofantasy wrote:
On Monday, 23 October 2017 at 22:22:55 UTC, Adam Wilson wrote:
On 10/23/17 08:21, Kagamin wrote:
[...]

Actually I think it fits perfectly with D, not for reason of
performance, but for reason of flexibility. D is a polyglot language, with by far the most number of methodologies supported in a single
language that I've ever encountered.

[...]

There is a lot of misunderstanding about async/await. It has nothing to do with "conservation of thread resources" or trading "raw performance
for an ability
to handle a truly massive number of simultaneous tasks". Async/await is just 'syntactic sugar' where the compiler re-writes your code into a state machine around APM (Asynchronous programming model which was introduced in .NET 2.0 sometime around 2002 I believe). That's all
there is to it, it makes your asynchronous code look and feel
synchronous.


The only parts of Async/Await that have anything to do with APM are the interop stubs. C#'s Async/Await is built around the Task Asynchronous Programming model (e.g. Task and Task<T>) the compiler lowers to those, not APM. A common misunderstanding is that Task/Task<T> is based on APM, it's not, Task uses fundamentally different code underneath. On Linux/macOS it actually uses libuv (at the end of the day all of these programming models are callback based).


I’ll throw in my 2 rubbles.

I actually worked on a VM that has async/await feature built-in (Dart language). It is a plain syntax sugar for Future/Promise explicit asynchrony where async automatically return Future[T] or Observable[T] (the latter is async stream).

Async function with awaits is then re-written as a single call-back with a basic state machine, each state corresponds to the line where you did await.

Example:

async double calculateTax(){
      double taxRate = await getTaxRates();
      double income = await getIncome();
      return taxRate * income;
}

Becomes roughly this (a bit more mechanical though):

Future!double calculateTax(){
       int state = 0;
       Promise!double __ret;
       double taxRate;
       double income;
       void cb() {
          if(state == 0) {
            state = 1;
            getTaxRates().andThen((double ret){
                 taxRate = ret;
                 cb();
            });
          }
          else if (state == 1) {
             state = 2;
             getIncome().andThen((double ret){
                 income = ret;
                 cb();
            });
           else if (state == 2){
                __ret.resolve(taxRate*income);
            }
       }
       cb();
  }

It doesn’t matter what mechanics you use to complete promises - be it IO scheduler a-la libuv or something else. Async/await is agnostic to that.

Still there is a fair amount of machinery to hide the rewrite from the user and in particular print stack trace as if it was normal sequential code.


Yes, C#'s async design does make code look and feel synchronous, and it was intentionally designed that way, but that is not *why* they did Async. That misunderstanding arises from an interview that Anders did in which he was asked why they held Async back for three years after announcing it at PDC08. In that same talk Anders specifically says that the purpose of the Async is to free up threads to continue execution, his example is a Windows Desktop Message Pump and fetching pictures from the internet (long-wait IO), but the principal applies to any thread. They held back async for three years because they needed to refine the language syntax to something that people could learn and apply in a reasonable amount of time. IIRC there is a Channel9 video where Anders explains the evolution of Async Await.

In other words - explicit asynchrony where a thread immediately returns with Future[T] and moves on to the next task. It’s just hidden by Async/Await.

Reply via email to