From 59ee1251d0eac2fcd3f2e7cb49fdcc5beb0fc6b7 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Tue, 5 Aug 2025 21:45:26 +0200 Subject: [PATCH] reduce EventWrapper allocations --- .../java/de/unixwork/ui/EventWrapper.java | 33 ++++---------- .../src/main/java/de/unixwork/ui/Toolkit.java | 44 +++++++++++++++++++ .../java/de/unixwork/ui/UiObjectFuncs.java | 16 +++++++ 3 files changed, 69 insertions(+), 24 deletions(-) diff --git a/ui-java/src/main/java/de/unixwork/ui/EventWrapper.java b/ui-java/src/main/java/de/unixwork/ui/EventWrapper.java index b018454..e6310ba 100644 --- a/ui-java/src/main/java/de/unixwork/ui/EventWrapper.java +++ b/ui-java/src/main/java/de/unixwork/ui/EventWrapper.java @@ -20,41 +20,22 @@ public class EventWrapper { // EventHandler object Arena objArena = obj.getArena(); // very important to use the obj arena - initCallback(objArena, "eventHandler"); + callback = Toolkit.getInstance().eventHandler; long index = obj.addEventHandler(handler); // use index as callback userdata, like casting it to intptr_t/void* userdata = MemorySegment.ofAddress(index); } - public EventWrapper(EventHandler handler) { + public EventWrapper(EventHandler handler, boolean oneshot) { Toolkit toolkit = Toolkit.getInstance(); - initCallback(toolkit.getStaticArena(), "globalEventHandler"); + callback = oneshot ? toolkit.oneshotEventHandler : toolkit.globalEventHandler; long index = toolkit.addEventHandler(handler); userdata = MemorySegment.ofAddress(index); } - private void initCallback(Arena arena, String methodName) { - Toolkit toolkit = Toolkit.getInstance(); - // void callback(UiEvent *event, void *userdata) - FunctionDescriptor handlerSig = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS); - - MethodHandle callbackMethod = null; - try { - callbackMethod = MethodHandles.lookup().findStatic( - EventWrapper.class, - methodName, - MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - - callback = toolkit.getLinker().upcallStub( - callbackMethod, - handlerSig, - arena); + public EventWrapper(EventHandler handler) { + this(handler, false); } public MemorySegment getCallback() { @@ -86,4 +67,8 @@ public class EventWrapper { handler.callback(e); } // else: error? } + + public static void oneshotEventHandler(MemorySegment event, MemorySegment userdata) { + + } } diff --git a/ui-java/src/main/java/de/unixwork/ui/Toolkit.java b/ui-java/src/main/java/de/unixwork/ui/Toolkit.java index b2c7f9f..21c5342 100644 --- a/ui-java/src/main/java/de/unixwork/ui/Toolkit.java +++ b/ui-java/src/main/java/de/unixwork/ui/Toolkit.java @@ -31,6 +31,7 @@ public class Toolkit { private MethodHandle mainFunc; private ArrayList eventHandlers = new ArrayList<>(); + private HashMap onshotEventHandlers = new HashMap<>(); protected MemorySegment listFirst; protected MemorySegment listNext; @@ -42,6 +43,10 @@ public class Toolkit { protected MemorySegment threadFuncPtr; + protected MemorySegment eventHandler; + protected MemorySegment globalEventHandler; + protected MemorySegment oneshotEventHandler; + private HashMap threadCallbacks = new HashMap<>(); private Toolkit(String appName) { @@ -196,6 +201,45 @@ public class Toolkit { } catch (IllegalAccessException e) { throw new RuntimeException(e); } + + // ui_callback wrapper + // void callback(UiEvent *event, void *userdata) + FunctionDescriptor handlerSig = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS); + + MethodHandle objCallbackMethod = null; + MethodHandle globalCallbackMethod = null; + MethodHandle oneshotCallbackMethod = null; + try { + objCallbackMethod = MethodHandles.lookup().findStatic( + EventWrapper.class, + "eventHandler", + MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); + globalCallbackMethod = MethodHandles.lookup().findStatic( + EventWrapper.class, + "globalEventHandler", + MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); + oneshotCallbackMethod = MethodHandles.lookup().findStatic( + EventWrapper.class, + "oneshotEventHandler", + MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + + eventHandler = linker.upcallStub( + objCallbackMethod, + handlerSig, + staticArena); + globalEventHandler = linker.upcallStub( + globalCallbackMethod, + handlerSig, + staticArena); + oneshotEventHandler = linker.upcallStub( + oneshotCallbackMethod, + handlerSig, + staticArena); } public static Toolkit getInstance() { diff --git a/ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java b/ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java index efe702c..220a61d 100644 --- a/ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java +++ b/ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java @@ -12,6 +12,8 @@ class UiObjectFuncs { public MethodHandle ui_simple_window; public MethodHandle ui_dialog_window_create; public MethodHandle ui_dialog_create; + public MethodHandle ui_openfiledialog; + public MethodHandle ui_savefiledialog; private UiObjectFuncs(Linker linker, SymbolLookup lib) { @@ -21,6 +23,8 @@ class UiObjectFuncs { FunctionDescriptor sigv_m = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS); // void func(void*, void*) FunctionDescriptor sigv_mm = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS); + FunctionDescriptor sigv_mimm = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS); + FunctionDescriptor sigv_mmmm = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS); MemorySegment ui_show_addr = lib.find("ui_show").orElseThrow(); MemorySegment ui_window_addr = lib.find("ui_window").orElseThrow(); @@ -28,6 +32,8 @@ class UiObjectFuncs { MemorySegment ui_simple_window_addr = lib.find("ui_simple_window").orElseThrow(); MemorySegment ui_dialog_window_create_addr = lib.find("ui_dialog_window_create").orElseThrow(); MemorySegment ui_dialog_create_addr = lib.find("ui_dialog_create").orElseThrow(); + MemorySegment ui_openfiledialog_addr = lib.find("ui_openfiledialog").orElseThrow(); + MemorySegment ui_savefiledialog_addr = lib.find("ui_savefiledialog").orElseThrow(); ui_show = linker.downcallHandle(ui_show_addr, sigv_m); ui_window = linker.downcallHandle(ui_window_addr, sigm_mm); @@ -35,6 +41,8 @@ class UiObjectFuncs { ui_simple_window = linker.downcallHandle(ui_simple_window_addr, sigm_mm); ui_dialog_window_create = linker.downcallHandle(ui_dialog_window_create_addr, sigm_mm); ui_dialog_create = linker.downcallHandle(ui_dialog_create_addr, sigv_mm); + ui_openfiledialog = linker.downcallHandle(ui_openfiledialog_addr, sigv_mimm); + ui_savefiledialog = linker.downcallHandle(ui_savefiledialog_addr, sigv_mmmm); } // must be called by the Toolkit constructor @@ -97,4 +105,12 @@ class UiObjectFuncs { throw new RuntimeException(e); } } + + public void openFileDialog(UiObject obj, int mode, EventHandler callback) { + EventWrapper ew = new EventWrapper(callback); + } + + public void saveFileDialog(UiObject obj, String name, EventHandler callback) { + + } } -- 2.47.3