|  | // 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. | 
|  |  | 
|  | import 'dart:async'; | 
|  |  | 
|  | /// Mutual exclusion. | 
|  | /// | 
|  | /// Usage: | 
|  | /// | 
|  | ///     var m = new Mutex(); | 
|  | /// | 
|  | ///     await m.acquire(); | 
|  | ///     try { | 
|  | ///       // critical section | 
|  | ///     } | 
|  | ///     finally { | 
|  | ///       m.release(); | 
|  | ///     } | 
|  | class Mutex { | 
|  | Completer<void> _lock; | 
|  |  | 
|  | /// Acquire a lock. | 
|  | /// | 
|  | /// Returns a [Future] that will be completed when the lock has been acquired. | 
|  | Future<void> acquire() async { | 
|  | while (_lock != null) { | 
|  | await _lock.future; | 
|  | } | 
|  | _lock = Completer<void>(); | 
|  | } | 
|  |  | 
|  | /// Run the given [criticalSection] with acquired mutex. | 
|  | Future<T> guard<T>(Future<T> Function() criticalSection) async { | 
|  | await acquire(); | 
|  | try { | 
|  | return await criticalSection(); | 
|  | } finally { | 
|  | release(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Release a lock. | 
|  | /// | 
|  | /// Release a lock that has been acquired. | 
|  | void release() { | 
|  | if (_lock == null) { | 
|  | throw StateError('No lock to release.'); | 
|  | } | 
|  | _lock.complete(); | 
|  | _lock = null; | 
|  | } | 
|  | } |