Line data Source code
1 : import 'dart:async'; 2 : 3 : /// A lock that ensures that only one async function executes at a time. 4 : class AsyncLock<T> { 5 : /// Creates a new [AsyncLock]. 6 0 : AsyncLock(this.function, {this.retainFutureErrors = false}); 7 : 8 : /// The function to execute. 9 : final FutureOr<T> Function() function; 10 : 11 : Completer<T>? _completer; 12 : 13 : /// Whether to retain errors or allow reentrancy until the Future completes 14 : /// successfully. 15 : final bool retainFutureErrors; 16 : 17 : /// Executes the given [function] and returns the value, but ensures that 18 : /// only one async function executes at a time. 19 0 : Future<T> execute() async => _completer?.future ?? _executeFunction(function); 20 : 21 : /// Creates a new [Completer], executes the given [function] and 22 : /// returns the value. 23 0 : Future<T> _executeFunction(FutureOr<T> Function() function) async { 24 0 : _completer = Completer<T>(); 25 : try { 26 0 : final result = await function(); 27 0 : _completer!.complete(result); 28 : return result; 29 : // ignore: avoid_catches_without_on_clauses 30 : } catch (error, stackTrace) { 31 0 : if (retainFutureErrors) { 32 0 : _completer!.completeError(error, stackTrace); 33 : } else { 34 0 : _completer = null; 35 : } 36 : rethrow; 37 : } 38 : } 39 : }