Fix lock not returning futures in right order

This commit is contained in:
Simon Binder 2021-05-28 21:59:47 +02:00
parent 6aa8c47d6a
commit 04caf09abb
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
3 changed files with 43 additions and 4 deletions

View File

@ -8,11 +8,13 @@ class Lock {
/// then calls [block] before further [synchronized] calls are allowed.
Future<T> synchronized<T>(FutureOr<T> Function() block) {
final previous = _last;
// We can use synchronous futures for _last since we always complete through
// callBlockAndComplete(), which is asynchronous.
final blockCompleted = Completer<void>.sync();
// This controller may not be sync: It must complete just after
// callBlockAndComplete completes.
final blockCompleted = Completer<void>();
_last = blockCompleted.future;
// Note: We can't use async/await here because this future must complete
// just before the blockCompleted completer.
Future<T> callBlockAndComplete() async {
try {
return await block();

View File

@ -0,0 +1,32 @@
@TestOn('vm')
import 'package:moor/ffi.dart';
import 'package:moor/moor.dart';
import 'package:test/test.dart';
import '../data/tables/todos.dart';
void main() {
test('regression test for #1232', () async {
// replace with generated table
final db = TodoDb(VmDatabase.memory());
final someTables = {db.todosTable};
await db.customStatement('create table tbl (x int)');
await db.customInsert('insert into tbl values(1)');
Stream<int> watchValue() => db
.customSelect('select * from tbl', readsFrom: someTables)
.map((row) => row.read<int>('x'))
.watchSingle();
expect(await watchValue().first, 1);
await Future.delayed(Duration.zero);
watchValue().listen(null);
await db.customUpdate('update tbl set x = 2',
updates: someTables, updateKind: UpdateKind.update);
expect(await watchValue().first, 2);
});
}

View File

@ -5,9 +5,14 @@ void main() {
test('synchronized runs code in sequence', () async {
final lock = Lock();
var i = 0;
final futures = List.generate(100, (index) => lock.synchronized(() => i++));
final completionOrder = <int>[];
final futures = List.generate(
100,
(index) => lock.synchronized(() => i++)
..whenComplete(() => completionOrder.add(index)));
final results = await Future.wait(futures);
expect(results, List.generate(100, (index) => index));
expect(completionOrder, List.generate(100, (index) => index));
});
}