// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.6

part of dart.cli;

/**
 * Synchronously blocks the calling isolate to wait for asynchronous events to
 * complete.
 *
 * If the [timeout] parameter is supplied, [waitForEvent] will return after
 * the specified timeout even if no events have occurred.
 *
 * This call does the following:
 * - suspends the current execution stack,
 * - runs the microtask queue until it is empty,
 * - waits until the message queue is not empty,
 * - handles messages on the message queue, plus their associated microtasks,
 *   until the message queue is empty,
 * - resumes the original stack.
 *
 * This function breaks the usual promise offered by Dart semantics that
 * message handlers and microtasks run to completion before the next message
 * handler or microtask begins to run. Of particular note is that use of this
 * function in a finally block will allow microtasks and message handlers to
 * run before all finally blocks for an exception have completed, possibly
 * breaking invariants in your program.
 *
 * This function will synchronously throw the first unhandled exception it
 * encounters in running the microtasks and message handlers as though the
 * throwing microtask or message handler was the only Dart invocation on the
 * stack. That is, unhandled exceptions in a microtask or message handler will
 * skip over stacks suspended in a call to [waitForEvent].
 *
 * Calls to this function may be nested. Earlier invocations will not
 * be able to complete until subsequent ones do. Messages that arrive after
 * a subsequent invocation are "consumed" by that invocation, and do not
 * unblock an earlier invocation. Please be aware that nesting calls to
 * [waitForEvent] can lead to deadlock when subsequent calls block to wait for
 * a condition that is only satisfied after an earlier call returns.
 *
 * Please note that this call is only available in the standalone command-line
 * Dart VM. Further, because it suspends the current execution stack until the
 * message queue is empty, even when running in the standalone command-line VM
 * there exists a risk that the current execution stack will be starved.
 */
external void _waitForEvent(int timeoutMillis);

@pragma("vm:entry-point")
void Function(int) _getWaitForEvent() => _waitForEvent;

// This should be set from C++ code by the embedder to wire up waitFor() to the
// native implementation. In the standalone VM this is set to _waitForEvent()
// above. If it is null, calling waitFor() will throw an UnsupportedError.
@pragma("vm:entry-point")
void Function(int) _waitForEventClosure;

class _WaitForUtils {
  static void waitForEvent({Duration timeout}) {
    if (_waitForEventClosure == null) {
      throw new UnsupportedError("waitFor is not supported by this embedder");
    }
    _waitForEventClosure(timeout == null ? 0 : max(1, timeout.inMilliseconds));
  }
}

/**
 * Suspends the stack, runs microtasks, and handles incoming events until
 * [future] completes.
 *
 * WARNING: EXPERIMENTAL. USE AT YOUR OWN RISK.
 *
 * This call does the following:
 * - While [future] is not completed:
 *   - suspends the current execution stack,
 *   - runs the microtask queue until it is empty,
 *   - waits until the message queue is not empty,
 *   - handles messages on the message queue, plus their associated microtasks,
 *     until the message queue is empty,
 *   - resumes the original stack.
 *
 * This function breaks the usual promise offered by Dart semantics that
 * message handlers and microtasks run to completion before the next message
 * handler or microtask begins to run. Of particular note is that use of this
 * function in a finally block will allow microtasks and message handlers to
 * run before all finally blocks for an exception have completed, possibly
 * breaking invariants in your program.
 *
 * Use of this function should be considered a last resort when it is not
 * possible to convert a Dart program entirely to an asynchronous style using
 * `async` and `await`.
 *
 * If the [Future] completes normally, its result is returned. If the [Future]
 * completes with an error, the error and stack trace are wrapped in an
 * [AsyncError] and thrown. If a microtask or message handler run during this
 * call results in an unhandled exception, that exception will be propagated
 * as though the microtask or message handler was the only Dart invocation on
 * the stack. That is, unhandled exceptions in a microtask or message handler
 * will skip over stacks suspended in a call to [waitFor].
 *
 * If the optional `timeout` parameter is passed, [waitFor] throws a
 * [TimeoutException] if the [Future] is not completed within the specified
 * period.
 *
 * Calls to [waitFor] may be nested. Earlier invocations will not complete
 * until subsequent ones do, but the completion of a subsequent invocation will
 * cause the previous invocation to wake up and check its [Future] for
 * completion.
 *
 * Please be aware that nesting calls to [waitFor] can lead to deadlock if
 * subsequent calls block waiting for a condition that is only satisfied when
 * an earlier call returns.
 */
T waitFor<T>(Future<T> future, {Duration timeout}) {
  T result;
  bool futureCompleted = false;
  Object error;
  StackTrace stacktrace;
  future.then((r) {
    futureCompleted = true;
    result = r;
  }, onError: (e, st) {
    error = e;
    stacktrace = st;
  });

  Stopwatch s;
  if (timeout != null) {
    s = new Stopwatch()..start();
  }
  Timer.run(() {}); // Enusre there is at least one message.
  while (!futureCompleted && (error == null)) {
    Duration remaining;
    if (timeout != null) {
      if (s.elapsed >= timeout) {
        throw new TimeoutException("waitFor() timed out", timeout);
      }
      remaining = timeout - s.elapsed;
    }
    _WaitForUtils.waitForEvent(timeout: remaining);
  }
  if (timeout != null) {
    s.stop();
  }
  Timer.run(() {}); // Ensure that previous calls to waitFor are woken up.

  if (error != null) {
    throw new AsyncError(error, stacktrace);
  }

  return result;
}
