synchronized<T> method
Executes computation
when lock is available.
Only one asynchronous block can run while the lock is retained.
If timeout
is specified, it will try to grab the lock and will not
call the computation callback and throw a TimeoutExpection
is the lock
cannot be grabbed in the given duration.
Implementation
@override
Future<T> synchronized<T>(FutureOr<T> Function() func,
{Duration? timeout}) async {
// Handle late synchronized section warning
final level = innerLevel;
// Check that we are still in the proper block
// zones could run outside the block so it could lead to an unexpected behavior
if (level >= innerLocks.length) {
throw StateError(
'This can happen if an inner synchronized block is spawned outside the block it was started from. Make sure the inner synchronized blocks are properly awaited');
}
final lock = innerLocks[level];
return lock.synchronized(() async {
innerLocks.add(BasicLock());
try {
var result = runZoned(() {
return func();
}, zoneValues: {this: level + 1});
if (result is Future) {
return await result;
} else {
return result;
}
} finally {
innerLocks.removeLast();
}
}, timeout: timeout);
}