Skip to content

Commit 922e11c

Browse files
[Alpha] Fix mutex reuse (#32)
* Fix Mutexed reuse in alpha
1 parent 79b0ff9 commit 922e11c

6 files changed

+31
-23
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.7.0-alpha.2
2+
3+
- Fix re-using a shared Mutex from https://github.com/powersync-ja/sqlite_async.dart/pull/31
4+
15
## 0.7.0-alpha.1
26

37
- Added initial support for web platform.
-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// This follows the pattern from here: https://stackoverflow.com/questions/58710226/how-to-import-platform-specific-dependency-in-flutter-dart-combine-web-with-an
22
// To conditionally export an implementation for either web or "native" platforms
33
// The sqlite library uses dart:ffi which is not supported on web
4-
54
export 'impl/isolate_connection_factory_impl.dart';

lib/src/native/native_isolate_connection_factory.dart

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ class IsolateConnectionFactoryImpl
4444
readOnly: readOnly,
4545
debugName: debugName,
4646
updates: updates.stream,
47-
closeFunction: () {
48-
openMutex.close();
47+
closeFunction: () async {
48+
await openMutex.close();
4949
updates.close();
5050
});
5151
}
@@ -83,7 +83,7 @@ class _IsolateUpdateListener {
8383
}
8484

8585
class _IsolateSqliteConnection extends SqliteConnectionImpl {
86-
final void Function() closeFunction;
86+
final Future<void> Function() closeFunction;
8787

8888
_IsolateSqliteConnection(
8989
{required super.openFactory,
@@ -97,6 +97,6 @@ class _IsolateSqliteConnection extends SqliteConnectionImpl {
9797
@override
9898
Future<void> close() async {
9999
await super.close();
100-
closeFunction();
100+
await closeFunction();
101101
}
102102
}

lib/src/native/native_isolate_mutex.dart

+3-17
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class SimpleMutex implements MutexImpl {
112112
class SerializedMutex implements Mutex {
113113
final SerializedPortClient client;
114114

115-
SerializedMutex(this.client);
115+
const SerializedMutex(this.client);
116116

117117
@override
118118
SharedMutex open() {
@@ -202,7 +202,8 @@ class SharedMutex implements Mutex {
202202
closed = true;
203203
// Wait for any existing locks to complete, then prevent any further locks from being taken out.
204204
await _acquire();
205-
client.fire(const _CloseMessage());
205+
// Release the lock
206+
_unlock();
206207
// Close client immediately after _unlock(),
207208
// so that we're sure no further locks are acquired.
208209
// This also cancels any lock request in process.
@@ -215,7 +216,6 @@ class _SharedMutexServer {
215216
Completer? unlock;
216217
late final SerializedMutex serialized;
217218
final Mutex mutex;
218-
bool closed = false;
219219

220220
late final PortServer server;
221221

@@ -230,11 +230,6 @@ class _SharedMutexServer {
230230
if (arg is _AcquireMessage) {
231231
var lock = Completer.sync();
232232
mutex.lock(() async {
233-
if (closed) {
234-
// The client will error already - we just need to ensure
235-
// we don't take out another lock.
236-
return;
237-
}
238233
assert(unlock == null);
239234
unlock = Completer.sync();
240235
lock.complete();
@@ -245,10 +240,6 @@ class _SharedMutexServer {
245240
} else if (arg is _UnlockMessage) {
246241
assert(unlock != null);
247242
unlock!.complete();
248-
} else if (arg is _CloseMessage) {
249-
// Unlock and close (from client side)
250-
closed = true;
251-
unlock?.complete();
252243
}
253244
}
254245

@@ -264,8 +255,3 @@ class _AcquireMessage {
264255
class _UnlockMessage {
265256
const _UnlockMessage();
266257
}
267-
268-
/// Unlock and close
269-
class _CloseMessage {
270-
const _CloseMessage();
271-
}

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: sqlite_async
22
description: High-performance asynchronous interface for SQLite on Dart and Flutter.
3-
version: 0.7.0-alpha.1
3+
version: 0.7.0-alpha.2
44
repository: https://github.com/powersync-ja/sqlite_async.dart
55
environment:
66
sdk: '>=3.2.0 <4.0.0'

test/mutex_test.dart

+19
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ void main() {
2323
expect(result, equals(5));
2424
}
2525
});
26+
27+
test('Re-use after closing', () async {
28+
// Test that shared locks can be opened and closed multiple times.
29+
final mutex = SimpleMutex();
30+
final serialized = mutex.shared;
31+
32+
final result = await Isolate.run(() async {
33+
return _lockInIsolate(serialized);
34+
});
35+
36+
final result2 = await Isolate.run(() async {
37+
return _lockInIsolate(serialized);
38+
});
39+
40+
await mutex.lock(() async {});
41+
42+
expect(result, equals(5));
43+
expect(result2, equals(5));
44+
});
2645
}, timeout: const Timeout(Duration(milliseconds: 5000)));
2746
}
2847

0 commit comments

Comments
 (0)