runPreciseInterval<T> function

void runPreciseInterval<T>(
  1. Duration interval,
  2. T callback(
    1. T state
    ), {
  3. required Completer<void> completer,
  4. dynamic state,
  5. Duration startBusyAt = const Duration(milliseconds: 1),
})

Run a callback at precise intervals.

The callback is called at the specified interval duration. This function uses a busy-wait loop to ensure that the callback is executed at the specified interval. In order to reduce CPU usage, it sleeps for a short duration before checking the elapsed time again. A Completer is used to signal when the loop should stop. The state parameter can be used to pass any additional data to the callback function, this keeps the state in the scope of the wrapping function and allows the callback to access it without needing to pass it as a parameter every time. @note that it is your job to ensure that the state will not perform operations that will cause memory leaks or unexpected behavior, such as accessing a closed stream or a disposed widget. The startBusyAt parameter specifies how long before the interval the function should start busy-waiting, this is the way that this function can achieve a precise interval. For example if you want a callback to be called with a 1Hz frequency, you can set the interval to 1 second and the startBusyAt to 1 millisecond. This means that the function will use low CPU usage for 999 milliseconds and then start busy-waiting for 1 millisecond.

Implementation

void runPreciseInterval<T>(
  Duration interval,
  T Function(T state) callback, {
  required Completer<void> completer,
  dynamic state,
  Duration startBusyAt = const Duration(milliseconds: 1),
}) {
  final sw = Stopwatch()..start();

  for (int i = 1; true; i++) {
    final nextAwake = interval * i;
    final toSleep = (nextAwake - sw.elapsed) - startBusyAt;
    if (toSleep > Duration.zero) {
      sleep(toSleep);
    }

    while (sw.elapsed < nextAwake) {}

    state = callback(state);
    if (completer.isCompleted) {
      break;
    }
  }
}