1
votes

I'm searching for the source of async/await implementations.

I would like to know how do they truly works in order to hack into future.then() to detect if there is code awaiting for execution or not.

Edit

This is what I'm willing to accomplish:

TrackingCompleter completer = new TrackingCompleter();
TrackingFuture future = completer.future;
print("isAwaited: ${future.isAwaited} (F)");
new Future.delayed(new Duration(milliseconds: 500), () {
  future.then((_) {
    print("executing sorping");
    print("isThenExecuted: ${future.thenExecuted} (F)");
    new Future.delayed(new Duration(milliseconds: 500), () {
      print("isThenExecuted: ${future.thenExecuted} (T)");
      exit(1);
    });
  });
  print("isAwaited: ${future.isAwaited} (T)");
  print("isThenExecuted: ${future.thenExecuted} (F)");
  completer.complete();
});

As far, that's working. What I'd like to do now is to detect if future.then is called manually in the code or automatically with an await statement.

1
AFAIK async/await is part of the compiler. The code is rewritten on-the-fly to future.then() and than executed only in this form. Perhaps you might investigate the event queue using Observatory dart-lang.github.io/observatory to get information about pending tasksGünter Zöchbauer

1 Answers

3
votes

The async/await implementation is based on futures. Basically, await creates a function that contains the rest of the current function (the "continuation" of the await expression), and then calls then on the future you await with that function as argument. There are more details needed to handle errors, but that's basically it.

In your case, if you want to know if future.then is called, I recommend just wrapping that particular future. Example:

import "package:async/async.dart";

class ThenWrapper<T> extends DelegatingFuture<T> {
  void Function(S Function(T), S Function(Object, StackTrace)) _callback;
  ThenWrapper(Future<T> future, this._callback): super(future);
  Future<S> then<S>(S onValue(T), {S onError(error, StackTrace st)}) {
    _callback(onValue, onError);
    return super.super(onValue, onError);
  }
}
...

TrackingFuture future = new ThenWrapper(completer.future, ...);

You can change the callback to do whatever you want.