Skip to content

Async lock + waitFor #9

Open
Open
@davidmartos96

Description

@davidmartos96

Hello!
Thank you for the simple and great library. I was considering using it as a way to synchronize writes to a SQLite database from different isolates, since SQLite only supports one writer at a time. Context: simolus3/drift#2760

The problem is that the SQLite library is async, but runLocked doesn't work with async callbacks as stated in the docs.

I managed to "solve" it (at least for my simple demo) by creating an async runLocked + waitFor. The problem is that waitFor is being removed in Dart 3.3.
How could this be solved in an alternative manner without the waitFor?

Thank you!

Future<R> runLockedAsync<R>(Future<R> Function() action) async {
    _lock();
    try {
      return waitFor(action());
    } finally {
      _unlock();
    }
  }

Demo:

import 'dart:isolate';
import 'dart:math';

import 'package:native_synchronization/primitives.dart';

void main() async {
  final mutex = Mutex();
  const numIsolates = 20;

  final fs = <Future>[];
  for (var i = 0; i < numIsolates; i++) {
    fs.add(runInIsolate(mutex, i));
  }

  await Future.wait(fs);
}

Future<void> runInIsolate(Mutex mutex, int id) async {
  final sendableMutex = mutex.asSendable;
  await Isolate.run(debugName: 'isolate_$id', () async {
    final r = Random();
    final mutex = sendableMutex.materialize();
    for (var i = 0; i < 100; i++) {
      await mutex.runLockedAsync(() async {
        print('ASYNC isolate $id inside $i');
        final ms = r.nextInt(50);
        await Future.delayed(Duration(milliseconds: ms));
      });

      await Future.delayed(Duration(milliseconds: 100));
    }
  });
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions