use *Async methods from gomuks

Performance improvement due to not needing as many Isolates.
This commit is contained in:
Henry Hiles 2026-10-21 22:57:26 -04:00
commit e14ab3e708
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
3 changed files with 47 additions and 33 deletions

2
gomuks

@ -1 +1 @@
Subproject commit ba82b6e31c87c99766a8366a72a9f07d643b323f
Subproject commit a65299d327e3a533e6c476b0450b09be91fbb827

View file

@ -106,39 +106,50 @@ class ClientController extends AsyncNotifier<int> {
return handle;
}
/// Calls gomuks with [data] as JSON, returning its decoded response.
Future<dynamic> callGomuksMethod(
Map<String, dynamic> data,
FutureOr<GomuksResponse> Function(int handle, GomuksBorrowedBuffer data)
callback,
void Function(
int handle,
GomuksOwnedBuffer data,
Pointer<NativeFunction<Void Function(GomuksResponse)>> callback,
)
call,
) async {
final bufferPointer = data.toGomuksBufferPtr();
final handle = await future;
final buffer = data.toGomuksOwnedBuffer();
final completer = Completer<dynamic>();
late final NativeCallable<Void Function(GomuksResponse)> callable;
callable = .listener((GomuksResponse response) {
callable.close();
try {
final json = response.buf.toJsonAndFree();
if (response.command.cast<Utf8>().toDartString() == "error") {
throw GomuksException(json.toString());
}
completer.complete(json);
} catch (error, stackTrace) {
completer.completeError(error, stackTrace);
}
});
try {
final handle = await future;
final response = await Isolate.run(
() => callback(handle, bufferPointer.ref),
);
final json = response.buf.toJsonAndFree();
if (response.command.cast<Utf8>().toDartString() == "error") {
throw GomuksException(json.toString());
}
return json;
} finally {
calloc
..free(bufferPointer.ref.base)
..free(bufferPointer);
call(handle, buffer, callable.nativeFunction);
} catch (_) {
// gomuks never got the call, so it won't respond or free the buffer
callable.close();
GomuksFreeBuffer(buffer);
rethrow;
}
return completer.future;
}
Future<PushNotification?> handlePush(Map<String, dynamic> data) async {
final response = await callGomuksMethod(
data,
(handle, data) async => GomuksHandlePush(handle, data),
);
final response = await callGomuksMethod(data, GomuksHandlePushAsync);
return response?["notification"] == null
? null
@ -148,11 +159,12 @@ class ClientController extends AsyncNotifier<int> {
Future<dynamic> _sendCommand(
String command, [
Map<String, dynamic> data = const {},
]) => callGomuksMethod(data, (handle, data) {
]) => callGomuksMethod(data, (handle, data, callback) {
final commandPointer = command.toNativeUtf8().cast<Char>();
try {
return GomuksSubmitCommand(handle, commandPointer, data);
GomuksSubmitCommandAsync(handle, commandPointer, data, callback);
} finally {
// gomuks copies the command name before returning
calloc.free(commandPointer);
}
});

View file

@ -19,19 +19,21 @@ extension GomuksOwnedBufferToX on GomuksOwnedBuffer {
}
extension JsonToGomuksBuffer on Map<String, dynamic> {
GomuksOwnedBuffer toGomuksOwnedBuffer() {
final bytes = utf8.encode(json.encode(this));
final buffer = GomuksAllocBuffer(bytes.length);
buffer.base.asTypedList(bytes.length).setAll(0, bytes);
return buffer;
}
Pointer<GomuksBorrowedBuffer> toGomuksBufferPtr() {
final jsonString = json.encode(this);
final bytes = utf8.encode(jsonString);
final bytes = utf8.encode(json.encode(this));
final dataPtr = calloc<Uint8>(bytes.length);
dataPtr.asTypedList(bytes.length).setAll(0, bytes);
final ptr = calloc<GomuksBorrowedBuffer>();
ptr.ref
..base = dataPtr
..length = bytes.length;
return ptr;
return calloc<GomuksBorrowedBuffer>()
..ref.base = dataPtr
..ref.length = bytes.length;
}
}