44 lines
1.2 KiB
Dart
44 lines
1.2 KiB
Dart
import 'dart:async';
|
|
|
|
/// Keeps incoming share files alive until every recipient finishes uploading.
|
|
class SharedFileUploads {
|
|
static final instance = SharedFileUploads();
|
|
|
|
final Map<String, int> _users = {};
|
|
final Map<String, Completer<void>> _idle = {};
|
|
|
|
void Function() retain(Iterable<String> paths) {
|
|
final files = paths.toSet();
|
|
for (final path in files) {
|
|
_users[path] = (_users[path] ?? 0) + 1;
|
|
_idle.putIfAbsent(path, Completer<void>.new);
|
|
}
|
|
var released = false;
|
|
return () {
|
|
if (released) return;
|
|
released = true;
|
|
for (final path in files) {
|
|
final remaining = _users[path]! - 1;
|
|
if (remaining == 0) {
|
|
_users.remove(path);
|
|
_idle.remove(path)!.complete();
|
|
} else {
|
|
_users[path] = remaining;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
Future<T> use<T>(Iterable<String> paths, Future<T> Function() upload) {
|
|
final release = retain(paths);
|
|
return Future<T>.sync(upload).whenComplete(release);
|
|
}
|
|
|
|
Future<void> waitUntilIdle(Iterable<String> paths) async {
|
|
await Future.wait([
|
|
for (final path in paths.toSet())
|
|
if (_idle[path] case final pending?) pending.future,
|
|
]);
|
|
}
|
|
}
|