tomWithFileLockAsync<T> function

Future<T> tomWithFileLockAsync<T>(
  1. File lockFile,
  2. Future<T> body(), {
  3. Duration staleAfter = tomFileLockStaleAfter,
  4. Duration timeout = const Duration(seconds: 30),
  5. void onBrokenLock(
    1. String warning
    )?,
})

tomWithFileLock for a caller that must not block its isolate while it waits: the waits between attempts are Future.delayed, and body may be asynchronous.

The exclusion is the same guard file, so it holds against every other holder of lockFile — another asynchronous task on this isolate as much as another isolate or process: the second task's exclusive create fails while the first holds the guard, exactly as a foreign process's would. Between the awaits of body the isolate runs other code, and that is the price of not blocking: code that must not run inside the critical section has to take the same guard to be kept out.

Implementation

Future<T> tomWithFileLockAsync<T>(
  File lockFile,
  Future<T> Function() body, {
  Duration staleAfter = tomFileLockStaleAfter,
  Duration timeout = const Duration(seconds: 30),
  void Function(String warning)? onBrokenLock,
}) async {
  final token = _newToken();
  final deadline = DateTime.now().add(timeout);
  while (!_attempt(lockFile, token, staleAfter, onBrokenLock)) {
    _failIfPast(deadline, lockFile, timeout);
    await Future<void>.delayed(_retryInterval);
  }
  try {
    return await body();
  } finally {
    _release(lockFile, token);
  }
}