diff options
-rw-r--r-- | doc/GlueGen_Mapping.html | 154 | ||||
-rw-r--r-- | doc/GlueGen_Mapping.md | 124 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/CMethodBindingEmitter.java | 2 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaConfiguration.java | 2 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaEmitter.java | 5 | ||||
-rw-r--r-- | src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java | 281 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java | 418 | ||||
-rw-r--r-- | src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg | 19 |
8 files changed, 734 insertions, 271 deletions
diff --git a/doc/GlueGen_Mapping.html b/doc/GlueGen_Mapping.html index e173c01..9520f34 100644 --- a/doc/GlueGen_Mapping.html +++ b/doc/GlueGen_Mapping.html @@ -1994,6 +1994,10 @@ Definition</h4> <p>If no keys are defined via <code>JavaCallbackKey</code>, or manually injected using a custom <code>SetCallback-KeyClass</code>, see below, the <code>CallbackFunction</code> has global scope.</p> +<p>In case keys are defined via <code>JavaCallbackKey</code> and no +manually injected custom <code>SetCallback-KeyClass</code> used, a +public <code>SetCallback-KeyClass</code> is being generated covering the +defined keys.</p> <p>Keys allow to limit the scope, i.e. map multiple <code>CallbackFunction</code> to the different keys.</p> <p>Key arguments must match in <code>SetCallbackFunction</code> to @@ -2008,18 +2012,62 @@ callback scope, i.e. the callback and all resources will be mapped to this key. The optional <code>SetCallback-KeyClass</code> may override this semantic.</li> </ul> -<p>Beside generating the actual function mapping of the API, additional -query methods are generated, passing the keys as its paramters</p> -<ul> -<li><code>boolean is<SetCallbackFunctionName>Mapped((key-arg)*)</code> -queries whether <code>SetCallbackFunctionName</code> is mapped.</li> -<li><code>ALBUFFERCALLBACKTYPESOFT get<SetCallbackFunctionName>((key-arg)*)</code> +<h4 +id="javacallback-generated-interfaces-classes-and-methods"><em>JavaCallback</em> +Generated Interfaces, Classes and Methods</h4> +<p>The public <code>CallbackFunction</code> interface is generated.</p> +<p>The default public <code>SetCallback-KeyClass</code> is generated if +keys are used and no custom class is specified, see above.</p> +<p>The public toolkit API <code>SetCallbackFunction</code> method is +being generated.</p> +<p>Additional public <em>maintenance</em> methods are generated. In case +keys are being used, they expect <code>SetCallback-KeyClass</code> as an +argument, otherwise they expect no argument for global scope.</p> +<p>In case keys are defined and hence <code>SetCallback-KeyClass</code> +used, the additional <em>maintenance</em> methods are:</p> +<ul> +<li><em>Set<<code>SetCallback-KeyClass</code>> +get<code>SetCallbackFunctionName</code>Keys()</em></li> +<li><em>boolean +is<code>SetCallbackFunctionName</code>Mapped(<code>SetCallback-KeyClass</code>)</em> +queries whether <code>SetCallbackFunctionName</code> is mapped to +key.</li> +<li><em><code>CallbackFunction</code> +get<code>SetCallbackFunctionName</code>(<code>SetCallback-KeyClass</code>)</em> returns the mapped <code>CallbackFunction</code>, null if not mapped</li> -<li><code>Object get<SetCallbackFunctionName>UserParam((key-arg)*)</code> +<li><em>Object +get<code>SetCallbackFunctionName</code>UserParam(<code>SetCallback-KeyClass</code>)</em> +returns the mapped <code>userParam</code> object, null if not +mapped</li> +<li><em>void +release<code>SetCallbackFunctionName</code>(<code>SetCallback-KeyClass</code>)</em> +releases the mapped <code>CallbackFunction</code> data set associated +via <code>SetCallbackFunctionName</code>.</li> +<li><em>int releaseAll<code>SetCallbackFunctionName</code>()</em> +releases complete mapped <code>CallbackFunction</code> data set +associated via <code>SetCallbackFunctionName</code>.</li> +</ul> +<p>In no keys are defined and hence global scope used, the additional +<em>maintenance</em> methods are:</p> +<ul> +<li><em>boolean is<code>SetCallbackFunctionName</code>Mapped()</em> +queries whether <code>SetCallbackFunctionName</code> is mapped.</li> +<li><em><code>CallbackFunction</code> +get<code>SetCallbackFunctionName</code>()</em> returns the mapped +<code>CallbackFunction</code>, null if not mapped</li> +<li><em>Object get<code>SetCallbackFunctionName</code>UserParam()</em> returns the mapped <code>userParam</code> object, null if not mapped</li> +<li><em>void release<code>SetCallbackFunctionName</code>()</em> releases +the mapped <code>CallbackFunction</code> data set associated via +<code>SetCallbackFunctionName</code>.</li> </ul> +<p>Note that the <em>release<code>SetCallbackFunctionName</code>(*)</em> +and <em>releaseAll<code>SetCallbackFunctionName</code>()</em> methods +are not the <em>proper toolkit API way</em> to remove the callback, try +to use original <code>SetCallbackFunctionName</code> API method instead +using a <code>null</code> <code>CallbackFunction</code> reference.</p> <h4 id="custom-setcallback-keyclass">Custom <code>SetCallback-KeyClass</code></h4> <p>The <code>SetCallback-KeyClass</code> is the optional user-written @@ -2094,10 +2142,11 @@ ArgumentIsString InjectMessageCallback01 1 # # This callback has no keys defines, rendering it of global scope! # -# Explicit queries are generated, passing the keys as paramters +# Explicit maintenance methods are generated, passing the keys as paramters # - `boolean isMessageCallback01Mapped()` queries whether `MessageCallback0` is mapped globally # - `T2_CallbackFunc01 getMessageCallback01()` returns the global T2_CallbackFunc01, null if not mapped # - `Object getMessageCallback01UserParam()` returns the global `usrParam` object, null if not mapped +# - `void releaseMessageCallback01()` releases callback data skipping toolkit API. Favor passing `null` callback ref to `MessageCallback01(..)` JavaCallbackDef MessageCallback01 T2_CallbackFunc01 2</code></pre> <p>Note that <a href="#libraryonload-librarybasename-for-jni_onload-"><code>LibraryOnLoad Bindingtest2</code></a> @@ -2121,34 +2170,20 @@ thread to the <code>JavaVM*</code> generating a new /** Entry point (through function pointer) to C language function: <br> <code>void MessageCallback01(T2_CallbackFunc01 cbFunc, void * usrParam)</code><br> */ public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam); + /** Returns if callback is mapped for <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ public boolean isMessageCallback01Mapped(); + + /** Returns T2_CallbackFunc01 callback for <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ public T2_CallbackFunc01 getMessageCallback01(); + + /** Returns user-param for <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ public Object getMessageCallback01UserParam(); + /** Releases callback data skipping toolkit API. Favor passing `null` callback ref to <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ + public void releaseMessageCallback01(); + /** Entry point (through function pointer) to C language function: <br> <code>void InjectMessageCallback01(size_t id, const char * msg)</code><br> */ public void InjectMessageCallback01(long id, String msg);</code></pre> -<p>Implementation utilizes the default <code>SetCallback-KeyClass</code> -implementation for -<code>void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code>, -which is key-less and hence minimalistic.</p> -<pre><code> private static class MessageCallback01Key { - MessageCallback01Key() { - } - @Override - public boolean equals(final Object o) { - if( this == o ) { - return true; - } - if( !(o instanceof MessageCallback01Key) ) { - return false; - } - return true; - } - @Override - public int hashCode() { - return 0; - } - }</code></pre> <h3 id="javacallback-example-2a-default-keyclass">JavaCallback Example 2a (Default <em>KeyClass</em>)</h3> <p>This examples is derived from OpenAL's @@ -2173,9 +2208,12 @@ buffer.</p> # The `buffer` key allows setting one callback per buffer-name, compatible with the `AL_SOFT_callback_buffer` spec. # # Explicit queries are generated, passing the keys as paramters - # - `boolean isAlBufferCallback0Mapped(int buffer)` queries whether `alBufferCallback0` is mapped to `buffer`. - # - `ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(int buffer)` returns the `buffer` mapped ALEVENTPROCSOFT, null if not mapped - # - `Object getAlBufferCallback0UserParam(int buffer)` returns the `buffer` mapped `userptr` object, null if not mapped + # - `Set<AlBufferCallback0Key> getAlBufferCallback0Keys()` returns set of Key { int buffer } + # - `boolean isAlBufferCallback0Mapped(AlBufferCallback0Key)` queries whether `alBufferCallback0` is mapped to `buffer`. + # - `ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(AlBufferCallback0Key)` returns the `buffer` mapped ALEVENTPROCSOFT, null if not mapped + # - `Object getAlBufferCallback0UserParam(AlBufferCallback0Key)` returns the `buffer` mapped `userptr` object, null if not mapped + # - `void releaseAllAlBufferCallback0()` releases all callback data mapped via Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to `alBufferCallback0(..)` + # - `void releaseAlBufferCallback0(AlBufferCallback0Key)` releases callback data mapped to Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to `alBufferCallback0(..)` JavaCallbackDef alBufferCallback0 ALBUFFERCALLBACKTYPESOFT 1 JavaCallbackKey alBufferCallback0 0</code></pre> <p>leading to the following interface</p> @@ -2186,23 +2224,11 @@ buffer.</p> } ... - - /** Entry point (through function pointer) to C language function: <br> <code>void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, void * userptr)</code><br> */ - public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr); - - public boolean isAlBufferCallback0Mapped(int buffer); - public ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(int buffer); - public Object getAlBufferCallback0UserParam(int buffer); - - /** Entry point (through function pointer) to C language function: <br> <code>void alEventCallbackInject(int eventType, int object, int param, const char * msg)</code><br> */ - public void alEventCallbackInject(int eventType, int object, int param, String msg); </code></pre> -<p>Implementation utilizes the default <code>SetCallback-KeyClass</code> -implementation for -<code>void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code>, -which uses one key, i.e. <code>buffer</code>.</p> -<pre><code> private static class AlBufferCallback0Key { - private final int buffer; - AlBufferCallback0Key(int buffer) { + + /** Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public static class AlBufferCallback0Key { + public final int buffer; + public AlBufferCallback0Key(int buffer) { this.buffer = buffer; } @Override @@ -2222,7 +2248,33 @@ which uses one key, i.e. <code>buffer</code>.</p> int hash = buffer; return hash; } - }</code></pre> + } + + ... + + /** Entry point (through function pointer) to C language function: <br> <code>void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, void * userptr)</code><br> */ + public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr); + + /** Returns set of Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public Set<AlBufferCallback0Key> getAlBufferCallback0Keys(); + + /** Returns whether callback Key { int buffer } is mapped for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public boolean isAlBufferCallback0Mapped(AlBufferCallback0Key key); + + /** Returns ALBUFFERCALLBACKTYPESOFT callback mapped to Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(AlBufferCallback0Key key); + + /** Returns user-param mapped to Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public Object getAlBufferCallback0UserParam(AlBufferCallback0Key key); + + /** Releases all callback data mapped via Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public int releaseAllAlBufferCallback0(); + + /** Releases callback data mapped to Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public void releaseAlBufferCallback0(AlBufferCallback0Key key); + + /** Entry point (through function pointer) to C language function: <br> <code>void alEventCallbackInject(int eventType, int object, int param, const char * msg)</code><br> */ + public void alEventCallbackInject(int eventType, int object, int param, String msg); </code></pre> <h3 id="javacallback-example-2b-custom-keyclass">JavaCallback Example 2b (Custom <em>KeyClass</em>)</h3> <p>Same as example 2a, but implementing a custom diff --git a/doc/GlueGen_Mapping.md b/doc/GlueGen_Mapping.md index 9a169d7..f43f7a6 100644 --- a/doc/GlueGen_Mapping.md +++ b/doc/GlueGen_Mapping.md @@ -800,6 +800,9 @@ If mapping the `CallbackFunction` to keys, the user must specify the same key ar If no keys are defined via `JavaCallbackKey`, or manually injected using a custom `SetCallback-KeyClass`, see below, the `CallbackFunction` has global scope. +In case keys are defined via `JavaCallbackKey` and no manually injected custom `SetCallback-KeyClass` used, +a public `SetCallback-KeyClass` is being generated covering the defined keys. + Keys allow to limit the scope, i.e. map multiple `CallbackFunction` to the different keys. Key arguments must match in `SetCallbackFunction` to remove a previously set `CallbackFunction`. @@ -808,11 +811,32 @@ Key arguments must match in `SetCallbackFunction` to remove a previously set `Ca - `SetCallbackFunction`: `SetCallbackFunction` name of the native toolkit API responsible to set the callback - `SetCallback-ParamIdx`: List of parameter indices of the `SetCallbackFunction`, denoting the key(s) limiting the callback scope, i.e. the callback and all resources will be mapped to this key. The optional `SetCallback-KeyClass` may override this semantic. -Beside generating the actual function mapping of the API, additional query methods are generated, passing the keys as its paramters -- `boolean is<SetCallbackFunctionName>Mapped((key-arg)*)` queries whether `SetCallbackFunctionName` is mapped. -- `ALBUFFERCALLBACKTYPESOFT get<SetCallbackFunctionName>((key-arg)*)` returns the mapped `CallbackFunction`, null if not mapped -- `Object get<SetCallbackFunctionName>UserParam((key-arg)*)` returns the mapped `userParam` object, null if not mapped +#### *JavaCallback* Generated Interfaces, Classes and Methods + +The public `CallbackFunction` interface is generated. + +The default public `SetCallback-KeyClass` is generated if keys are used and no custom class is specified, see above. + +The public toolkit API `SetCallbackFunction` method is being generated. + +Additional public *maintenance* methods are generated. In case keys are being used, they expect `SetCallback-KeyClass` as an argument, otherwise they expect no argument for global scope. + +In case keys are defined and hence `SetCallback-KeyClass` used, the additional *maintenance* methods are: +- *Set<`SetCallback-KeyClass`> get`SetCallbackFunctionName`Keys()* +- *boolean is`SetCallbackFunctionName`Mapped(`SetCallback-KeyClass`)* queries whether `SetCallbackFunctionName` is mapped to key. +- *`CallbackFunction` get`SetCallbackFunctionName`(`SetCallback-KeyClass`)* returns the mapped `CallbackFunction`, null if not mapped +- *Object get`SetCallbackFunctionName`UserParam(`SetCallback-KeyClass`)* returns the mapped `userParam` object, null if not mapped +- *void release`SetCallbackFunctionName`(`SetCallback-KeyClass`)* releases the mapped `CallbackFunction` data set associated via `SetCallbackFunctionName`. +- *int releaseAll`SetCallbackFunctionName`()* releases complete mapped `CallbackFunction` data set associated via `SetCallbackFunctionName`. + +In no keys are defined and hence global scope used, the additional *maintenance* methods are: +- *boolean is`SetCallbackFunctionName`Mapped()* queries whether `SetCallbackFunctionName` is mapped. +- *`CallbackFunction` get`SetCallbackFunctionName`()* returns the mapped `CallbackFunction`, null if not mapped +- *Object get`SetCallbackFunctionName`UserParam()* returns the mapped `userParam` object, null if not mapped +- *void release`SetCallbackFunctionName`()* releases the mapped `CallbackFunction` data set associated via `SetCallbackFunctionName`. +Note that the *release`SetCallbackFunctionName`(\*)* and *releaseAll`SetCallbackFunctionName`()* methods are not the *proper toolkit API way* to remove the callback, +try to use original `SetCallbackFunctionName` API method instead using a `null` `CallbackFunction` reference. #### Custom `SetCallback-KeyClass` @@ -872,10 +896,11 @@ ArgumentIsString InjectMessageCallback01 1 # # This callback has no keys defines, rendering it of global scope! # -# Explicit queries are generated, passing the keys as paramters +# Explicit maintenance methods are generated, passing the keys as paramters # - `boolean isMessageCallback01Mapped()` queries whether `MessageCallback0` is mapped globally # - `T2_CallbackFunc01 getMessageCallback01()` returns the global T2_CallbackFunc01, null if not mapped # - `Object getMessageCallback01UserParam()` returns the global `usrParam` object, null if not mapped +# - `void releaseMessageCallback01()` releases callback data skipping toolkit API. Favor passing `null` callback ref to `MessageCallback01(..)` JavaCallbackDef MessageCallback01 T2_CallbackFunc01 2 ``` @@ -898,37 +923,22 @@ public interface Bindingtest2 { /** Entry point (through function pointer) to C language function: <br> <code>void MessageCallback01(T2_CallbackFunc01 cbFunc, void * usrParam)</code><br> */ public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam); + /** Returns if callback is mapped for <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ public boolean isMessageCallback01Mapped(); + + /** Returns T2_CallbackFunc01 callback for <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ public T2_CallbackFunc01 getMessageCallback01(); + + /** Returns user-param for <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ public Object getMessageCallback01UserParam(); + /** Releases callback data skipping toolkit API. Favor passing `null` callback ref to <br> <code> public void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)</code> **/ + public void releaseMessageCallback01(); + /** Entry point (through function pointer) to C language function: <br> <code>void InjectMessageCallback01(size_t id, const char * msg)</code><br> */ public void InjectMessageCallback01(long id, String msg); ``` -Implementation utilizes the default `SetCallback-KeyClass` implementation for `void MessageCallback01(T2_CallbackFunc01 cbFunc, Object usrParam)`, -which is key-less and hence minimalistic. -``` - private static class MessageCallback01Key { - MessageCallback01Key() { - } - @Override - public boolean equals(final Object o) { - if( this == o ) { - return true; - } - if( !(o instanceof MessageCallback01Key) ) { - return false; - } - return true; - } - @Override - public int hashCode() { - return 0; - } - } -``` - ### JavaCallback Example 2a (Default *KeyClass*) This examples is derived from OpenAL's `AL_SOFT_callback_buffer` extension. @@ -956,9 +966,12 @@ and the following GlueGen configuration # The `buffer` key allows setting one callback per buffer-name, compatible with the `AL_SOFT_callback_buffer` spec. # # Explicit queries are generated, passing the keys as paramters - # - `boolean isAlBufferCallback0Mapped(int buffer)` queries whether `alBufferCallback0` is mapped to `buffer`. - # - `ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(int buffer)` returns the `buffer` mapped ALEVENTPROCSOFT, null if not mapped - # - `Object getAlBufferCallback0UserParam(int buffer)` returns the `buffer` mapped `userptr` object, null if not mapped + # - `Set<AlBufferCallback0Key> getAlBufferCallback0Keys()` returns set of Key { int buffer } + # - `boolean isAlBufferCallback0Mapped(AlBufferCallback0Key)` queries whether `alBufferCallback0` is mapped to `buffer`. + # - `ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(AlBufferCallback0Key)` returns the `buffer` mapped ALEVENTPROCSOFT, null if not mapped + # - `Object getAlBufferCallback0UserParam(AlBufferCallback0Key)` returns the `buffer` mapped `userptr` object, null if not mapped + # - `void releaseAllAlBufferCallback0()` releases all callback data mapped via Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to `alBufferCallback0(..)` + # - `void releaseAlBufferCallback0(AlBufferCallback0Key)` releases callback data mapped to Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to `alBufferCallback0(..)` JavaCallbackDef alBufferCallback0 ALBUFFERCALLBACKTYPESOFT 1 JavaCallbackKey alBufferCallback0 0 ``` @@ -972,24 +985,11 @@ leading to the following interface } ... - - /** Entry point (through function pointer) to C language function: <br> <code>void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, void * userptr)</code><br> */ - public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr); - - public boolean isAlBufferCallback0Mapped(int buffer); - public ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(int buffer); - public Object getAlBufferCallback0UserParam(int buffer); - - /** Entry point (through function pointer) to C language function: <br> <code>void alEventCallbackInject(int eventType, int object, int param, const char * msg)</code><br> */ - public void alEventCallbackInject(int eventType, int object, int param, String msg); -``` - -Implementation utilizes the default `SetCallback-KeyClass` implementation for `void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)`, -which uses one key, i.e. `buffer`. -``` - private static class AlBufferCallback0Key { - private final int buffer; - AlBufferCallback0Key(int buffer) { + + /** Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public static class AlBufferCallback0Key { + public final int buffer; + public AlBufferCallback0Key(int buffer) { this.buffer = buffer; } @Override @@ -1010,6 +1010,32 @@ which uses one key, i.e. `buffer`. return hash; } } + + ... + + /** Entry point (through function pointer) to C language function: <br> <code>void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, void * userptr)</code><br> */ + public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr); + + /** Returns set of Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public Set<AlBufferCallback0Key> getAlBufferCallback0Keys(); + + /** Returns whether callback Key { int buffer } is mapped for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public boolean isAlBufferCallback0Mapped(AlBufferCallback0Key key); + + /** Returns ALBUFFERCALLBACKTYPESOFT callback mapped to Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(AlBufferCallback0Key key); + + /** Returns user-param mapped to Key { int buffer } for <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public Object getAlBufferCallback0UserParam(AlBufferCallback0Key key); + + /** Releases all callback data mapped via Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public int releaseAllAlBufferCallback0(); + + /** Releases callback data mapped to Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to <br> <code> public void alBufferCallback0(int buffer, int format, int freq, ALBUFFERCALLBACKTYPESOFT callback, Object userptr)</code> **/ + public void releaseAlBufferCallback0(AlBufferCallback0Key key); + + /** Entry point (through function pointer) to C language function: <br> <code>void alEventCallbackInject(int eventType, int object, int param, const char * msg)</code><br> */ + public void alEventCallbackInject(int eventType, int object, int param, String msg); ``` ### JavaCallback Example 2b (Custom *KeyClass*) diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java index 43d11b7..9be4a36 100644 --- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java @@ -569,7 +569,7 @@ public class CMethodBindingEmitter extends FunctionEmitter { final String capIfaceName = CodeGenUtils.capitalizeString( getInterfaceName() ); unit.emitln("JNIEXPORT void JNICALL"); unit.emit(JavaEmitter.getJNIMethodNamePrefix(getJavaPackageName(), getJavaClassName())); - unit.emitln("_release"+capIfaceName+"MapImpl(JNIEnv *env, jobject _unused, jlong jnativeUserParam) {"); + unit.emitln("_release"+capIfaceName+"Impl(JNIEnv *env, jobject _unused, jlong jnativeUserParam) {"); unit.emitln(" T_"+jcbNativeBasename+"* nativeUserParam = (T_"+jcbNativeBasename+"*) (intptr_t) jnativeUserParam;"); unit.emitln(" if( NULL != nativeUserParam ) {"); unit.emitln(" (*env)->DeleteGlobalRef(env, nativeUserParam->cbFunc);"); diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java index 1fe2747..3e2e680 100644 --- a/src/java/com/jogamp/gluegen/JavaConfiguration.java +++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java @@ -2293,6 +2293,7 @@ public class JavaConfiguration { boolean setFuncProcessed; int setFuncCBParamIdx; int setFuncUserParamIdx; + boolean keyClassEmitted; public JavaCallbackInfo(final String cbFuncTypeName, final String cbSimpleClazzName, final String cbFQClazzName, final String cbMethodSignature, final FunctionType cbFuncType, final MethodBinding cbFuncBinding, final int cbFuncUserParamIdx, @@ -2326,6 +2327,7 @@ public class JavaConfiguration { this.setFuncProcessed = false; this.setFuncCBParamIdx = -1; this.setFuncUserParamIdx = -1; + this.keyClassEmitted = false; } public void setFuncProcessed(final int cbParamIdx, final int userParamIdx) { diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index 7674e1f..c00d2ed 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -74,6 +74,7 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.os.MachineDataInfo; import com.jogamp.common.util.ArrayHashMap; +import com.jogamp.common.util.HashUtil; import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider; import com.jogamp.gluegen.JavaConfiguration.JavaCallbackDef; import com.jogamp.gluegen.JavaConfiguration.JavaCallbackInfo; @@ -2930,6 +2931,10 @@ public class JavaEmitter implements GlueEmitter { imports.add(DynamicLookupHelper.class.getPackage().getName()+".*"); imports.add(Buffers.class.getPackage().getName()+".*"); imports.add(Buffer.class.getPackage().getName()+".*"); + imports.add(HashUtil.class.getPackage().getName()+".*"); + imports.add("java.util.Set"); + imports.add("java.util.Map"); + imports.add("java.util.HashMap"); imports.add("java.nio.charset.Charset"); imports.add("java.nio.charset.StandardCharsets"); diff --git a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java index 977596f..985056d 100644 --- a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java @@ -50,8 +50,6 @@ import com.jogamp.gluegen.cgram.types.Type; import java.io.PrintWriter; import java.text.MessageFormat; -import java.util.Arrays; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -459,17 +457,31 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { private static final boolean DEBUG_JAVACALLBACK = false; - private final void emitJavaCallbackKeyClass(final String KeyClassName) { - unit.emitln(" private static class "+KeyClassName+" {"); + private final void emitJavaCallbackBirefAPIDoc(final String actionText, final String relationToKey, final String noKeyText, final String relationToFunc) { + unit.emit(" /** "+actionText); + if( javaCallback.setFuncKeyIndices.size() > 0 ) { + unit.emit(relationToKey); + unit.emit("Key { "+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+" } "); + } else { + unit.emit(noKeyText); + } + unit.emit(relationToFunc); + unit.emit("<br> <code>"); + emitSignature(); + unit.emitln("</code> **/"); + } + private final void emitJavaCallbackKeyClass(final String capIfaceName, final String keyClassName) { + emitJavaCallbackBirefAPIDoc("", "", "", "for "); + unit.emitln(" public static class "+keyClassName+" {"); binding.forEachParameter( ( final int idx, final int consumedCount, final Type cType, final JavaType jType, final String name ) -> { if( !cType.isVoid() && javaCallback.setFuncKeyIndices.contains(idx) ) { - unit.emitln(" private final "+jType+" "+name+";"); + unit.emitln(" public final "+jType+" "+name+";"); return true; } else { return false; } } ); - unit.emitln(" "+KeyClassName+"("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+") {"); + unit.emitln(" public "+keyClassName+"("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+") {"); binding.forEachParameter( ( final int idx, final int consumedCount, final Type cType, final JavaType jType, final String name ) -> { if( !cType.isVoid() && javaCallback.setFuncKeyIndices.contains(idx) ) { unit.emitln(" this."+name+" = "+name+";"); @@ -484,14 +496,14 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { unit.emitln(" if( this == o ) {"); unit.emitln(" return true;"); unit.emitln(" }"); - unit.emitln(" if( !(o instanceof "+KeyClassName+") ) {"); + unit.emitln(" if( !(o instanceof "+keyClassName+") ) {"); unit.emitln(" return false;"); unit.emitln(" }"); { final int count = binding.forEachParameter( ( final int idx, final int consumedCount, final Type cType, final JavaType jType, final String name ) -> { if( !cType.isVoid() && javaCallback.setFuncKeyIndices.contains(idx) ) { if( 0 == consumedCount ) { - unit.emitln(" final "+KeyClassName+" o2 = ("+KeyClassName+")o;"); + unit.emitln(" final "+keyClassName+" o2 = ("+keyClassName+")o;"); unit.emit (" return "); } else { unit.emitln(" &&"); @@ -526,7 +538,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } if( jType.isPrimitive() ) { if( jType.isLong() ) { - unit.emitln("Long.valueOf( "+name+" ).hashCode();"); + unit.emitln("HashUtil.getAddrHash32_EqualDist( "+name+" );"); } else { unit.emitln(name+";"); } @@ -550,14 +562,13 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { } unit.emitln(" }"); unit.emitln(" }"); - unit.emitln(); } - private final void emitJavaCallbackUsrParamClass(final String UsrParamClassName) { - unit.emitln(" private static class "+UsrParamClassName+" {"); + private final void emitJavaCallbackDataClass(final String capIfaceName, final String dataClassName) { + unit.emitln(" private static class "+dataClassName+" {"); unit.emitln(" final "+javaCallback.cbFuncTypeName+" func;"); unit.emitln(" final Object param;"); unit.emitln(" final long nativeParam;"); - unit.emitln(" "+UsrParamClassName+"("+javaCallback.cbFuncTypeName+" func, Object param, long nativeParam) {"); + unit.emitln(" "+dataClassName+"("+javaCallback.cbFuncTypeName+" func, Object param, long nativeParam) {"); unit.emitln(" this.func = func;"); unit.emitln(" this.param = param;"); unit.emitln(" this.nativeParam = nativeParam;"); @@ -586,68 +597,193 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { if( null != javaCallback && !isPrivateNativeMethod ) { final String capIfaceName = CodeGenUtils.capitalizeString( getInterfaceName() ); final String lowIfaceName = CodeGenUtils.decapitalizeString( getInterfaceName() ); + final String lockInstanceName = lowIfaceName+"Lock"; + final String dataMapInstanceName = lowIfaceName+"DataMap"; + final String dataInstanceName = lowIfaceName+"Data"; + final boolean useDataMap = javaCallback.setFuncKeyIndices.size() > 0; + final boolean customKeyClass; + final String KeyClassName; + if( null != javaCallback.setFuncKeyClassName ) { + customKeyClass = true;; + KeyClassName = javaCallback.setFuncKeyClassName; + } else { + customKeyClass = false; + KeyClassName = CodeGenUtils.capitalizeString(capIfaceName+"Key"); + } + final String DataClassName = CodeGenUtils.capitalizeString( javaCallback.cbFuncTypeName+"Data" ); + final String fqUsrParamClassName = cfg.packageName()+"."+cfg.className()+"."+DataClassName; unit.emitln(); if( isInterface() ) { - unit.emitln(" public boolean is"+capIfaceName+"Mapped("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); - unit.emitln(" public "+javaCallback.cbFuncTypeName+" get"+capIfaceName+"("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); - unit.emitln(" public Object get"+capIfaceName+"UserParam("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); + if( useDataMap ) { + if( !customKeyClass && !javaCallback.keyClassEmitted ) { + emitJavaCallbackKeyClass(capIfaceName, KeyClassName); + unit.emitln(); + javaCallback.keyClassEmitted = true; + } + emitJavaCallbackBirefAPIDoc("Returns ", "set of ", "", "for "); + unit.emitln(" public Set<"+KeyClassName+"> get"+capIfaceName+"Keys();"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Returns ", "whether callback ", "if callback ", "is mapped for "); + unit.emitln(" public boolean is"+capIfaceName+"Mapped("+KeyClassName+" key);"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Returns "+javaCallback.cbFuncTypeName+" callback ", "mapped to ", "", "for "); + unit.emitln(" public "+javaCallback.cbFuncTypeName+" get"+capIfaceName+"("+KeyClassName+" key);"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Returns user-param ", "mapped to ", "", "for "); + unit.emitln(" public Object get"+capIfaceName+"UserParam("+KeyClassName+" key);"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Releases all callback data ", "mapped via ", "", "skipping toolkit API. Favor passing `null` callback ref to "); + unit.emitln(" public int releaseAll"+capIfaceName+"();"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Releases callback data ", "mapped to ", "", "skipping toolkit API. Favor passing `null` callback ref to "); + unit.emitln(" public void release"+capIfaceName+"("+KeyClassName+" key);"); + unit.emitln(); + } else { + emitJavaCallbackBirefAPIDoc("Returns ", "whether callback ", "if callback ", "is mapped for "); + unit.emitln(" public boolean is"+capIfaceName+"Mapped();"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Returns "+javaCallback.cbFuncTypeName+" callback ", "mapped to ", "", "for "); + unit.emitln(" public "+javaCallback.cbFuncTypeName+" get"+capIfaceName+"();"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Returns user-param ", "mapped to ", "", "for "); + unit.emitln(" public Object get"+capIfaceName+"UserParam();"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Releases callback data ", "", "", "skipping toolkit API. Favor passing `null` callback ref to "); + unit.emitln(" public void release"+capIfaceName+"();"); + unit.emitln(); + } } else { - final String usrMapInstanceName = lowIfaceName+"UsrMap"; - final boolean customKeyClass; - final String KeyClassName; - if( null != javaCallback.setFuncKeyClassName ) { - customKeyClass = true;; - KeyClassName = javaCallback.setFuncKeyClassName; + if( useDataMap ) { + if( !customKeyClass && !javaCallback.keyClassEmitted ) { + emitJavaCallbackKeyClass(capIfaceName, KeyClassName); + unit.emitln(); + javaCallback.keyClassEmitted = true; + } + emitJavaCallbackBirefAPIDoc("Returns ", "set of ", "", "for "); + unit.emitln(" public final Set<"+KeyClassName+"> get"+capIfaceName+"Keys() {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" return "+dataMapInstanceName+".keySet();"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Returns ", "whether callback ", "if callback ", "is mapped for "); + unit.emitln(" public final boolean is"+capIfaceName+"Mapped("+KeyClassName+" key) {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" return null != "+dataMapInstanceName+".get(key);"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + + emitJavaCallbackBirefAPIDoc("Returns "+javaCallback.cbFuncTypeName+" callback ", "mapped to ", "", "for "); + unit.emitln(" public final "+javaCallback.cbFuncTypeName+" get"+capIfaceName+"("+KeyClassName+" key) {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" final "+DataClassName+" value = "+dataMapInstanceName+".get(key);"); + unit.emitln(" return null != value ? value.func : null;"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + + emitJavaCallbackBirefAPIDoc("Returns user-param ", "mapped to ", "", "for "); + unit.emitln(" public final Object get"+capIfaceName+"UserParam("+KeyClassName+" key) {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" final "+DataClassName+" value = "+dataMapInstanceName+".get(key);"); + unit.emitln(" return null != value ? value.param : null;"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Releases all callback data ", "mapped via ", "", "skipping toolkit API. Favor passing `null` callback ref to "); + unit.emitln(" public final int releaseAll"+capIfaceName+"() {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" final Set<"+KeyClassName+"> keySet = "+dataMapInstanceName+".keySet();"); + unit.emitln(" final "+KeyClassName+"[] keys = keySet.toArray(new "+KeyClassName+"[keySet.size()]);"); + unit.emitln(" for(int i=0; i<keys.length; ++i) {"); + unit.emitln(" final "+KeyClassName+" key = keys[i];"); + unit.emitln(" release"+capIfaceName+"(key);"); + unit.emitln(" }"); + unit.emitln(" return keys.length;"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + emitJavaCallbackBirefAPIDoc("Releases callback data ", "mapped to ", "", "skipping toolkit API. Favor passing `null` callback ref to "); + unit.emitln(" public final void release"+capIfaceName+"("+KeyClassName+" key) {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" final "+DataClassName+" value = "+dataMapInstanceName+".remove(key);"); + if( DEBUG_JAVACALLBACK ) { + unit.emitln(" System.err.println(\"ZZZ Release \"+key+\" -> value.nativeParam 0x\"+Long.toHexString(null!=value?value.nativeParam:0));"); + } + unit.emitln(" if( null != value ) {"); + unit.emitln(" release"+capIfaceName+"Impl(value.nativeParam);"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(" }"); } else { - customKeyClass = false; - KeyClassName = CodeGenUtils.capitalizeString(capIfaceName+"Key"); + emitJavaCallbackBirefAPIDoc("Returns ", "whether callback ", "if callback ", "is mapped for "); + unit.emitln(" public final boolean is"+capIfaceName+"Mapped() {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" return null != "+dataInstanceName+";"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + + emitJavaCallbackBirefAPIDoc("Returns "+javaCallback.cbFuncTypeName+" callback ", "mapped to ", "", "for "); + unit.emitln(" public final "+javaCallback.cbFuncTypeName+" get"+capIfaceName+"() {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" final "+DataClassName+" value = "+dataInstanceName+";"); + unit.emitln(" return null != value ? value.func : null;"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + + emitJavaCallbackBirefAPIDoc("Returns user-param ", "mapped to ", "", "for "); + unit.emitln(" public final Object get"+capIfaceName+"UserParam() {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" final "+DataClassName+" value = "+dataInstanceName+";"); + unit.emitln(" return null != value ? value.param : null;"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(); + + emitJavaCallbackBirefAPIDoc("Releases callback data ", "", "", "skipping toolkit API. Favor passing `null` callback ref to "); + unit.emitln(" public final void release"+capIfaceName+"() {"); + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); + unit.emitln(" final "+DataClassName+" value = "+dataInstanceName+";"); + unit.emitln(" "+dataInstanceName+" = null;"); + if( DEBUG_JAVACALLBACK ) { + unit.emitln(" System.err.println(\"ZZZ Release \"+key+\" -> value.nativeParam 0x\"+Long.toHexString(null!=value?value.nativeParam:0));"); + } + unit.emitln(" if( null != value ) {"); + unit.emitln(" release"+capIfaceName+"Impl(value.nativeParam);"); + unit.emitln(" }"); + unit.emitln(" }"); + unit.emitln(" }"); + } + unit.emitln(" private native void release"+capIfaceName+"Impl(long nativeUserParam);"); + unit.emitln(); + unit.emitln(" private final void add"+capIfaceName+"("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, true).toString()+DataClassName+" value) {"); + if( useDataMap ) { + unit.emitln(" final "+KeyClassName+" key = new "+KeyClassName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); + unit.emitln(" final "+DataClassName+" old = "+dataMapInstanceName+".put(key, value);"); + } else { + unit.emitln(" final "+DataClassName+" old = "+dataInstanceName+";"); + unit.emitln(" "+dataInstanceName+" = value;"); } - final String UsrParamClassName = CodeGenUtils.capitalizeString( javaCallback.cbFuncTypeName+"UserParam" ); - final String fqUsrParamClassName = cfg.packageName()+"."+cfg.className()+"."+UsrParamClassName; - unit.emitln(" public final boolean is"+capIfaceName+"Mapped("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+") {"); - unit.emitln(" final "+KeyClassName+" key = new "+KeyClassName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); - unit.emitln(" return null != "+usrMapInstanceName+".get(key);"); - unit.emitln(" }"); - unit.emitln(" public final "+javaCallback.cbFuncTypeName+" get"+capIfaceName+"("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+") {"); - unit.emitln(" final "+KeyClassName+" key = new "+KeyClassName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); - unit.emitln(" final "+UsrParamClassName+" value = "+usrMapInstanceName+".get(key);"); - unit.emitln(" return null != value ? value.func : null;"); - unit.emitln(" }"); - unit.emitln(" public final Object get"+capIfaceName+"UserParam("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+") {"); - unit.emitln(" final "+KeyClassName+" key = new "+KeyClassName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); - unit.emitln(" final "+UsrParamClassName+" value = "+usrMapInstanceName+".get(key);"); - unit.emitln(" return null != value ? value.param : null;"); - unit.emitln(" }"); - unit.emitln(" private final void add"+capIfaceName+"Map("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, true).toString()+UsrParamClassName+" value) {"); - unit.emitln(" final "+KeyClassName+" key = new "+KeyClassName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); - unit.emitln(" final "+UsrParamClassName+" old = "+usrMapInstanceName+".put(key, value);"); if( DEBUG_JAVACALLBACK ) { unit.emitln(" System.err.println(\"ZZZ Map \"+key+\" -> value.nativeParam 0x\"+Long.toHexString(null!=value?value.nativeParam:0));"); } unit.emitln(" if( null != old ) {"); - unit.emitln(" release"+capIfaceName+"MapImpl(old.nativeParam);"); + unit.emitln(" release"+capIfaceName+"Impl(old.nativeParam);"); unit.emitln(" }"); unit.emitln(" }"); - unit.emitln(" private final void release"+capIfaceName+"Map("+binding.getJavaSelectParameter(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+") {"); - unit.emitln(" final "+KeyClassName+" key = new "+KeyClassName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); - unit.emitln(" final "+UsrParamClassName+" value = "+usrMapInstanceName+".remove(key);"); - if( DEBUG_JAVACALLBACK ) { - unit.emitln(" System.err.println(\"ZZZ Release \"+key+\" -> value.nativeParam 0x\"+Long.toHexString(null!=value?value.nativeParam:0));"); - } - unit.emitln(" if( null != value ) {"); - unit.emitln(" release"+capIfaceName+"MapImpl(value.nativeParam);"); - unit.emitln(" }"); - unit.emitln(" }"); - unit.emitln(" private native void release"+capIfaceName+"MapImpl(long nativeUserParam);"); - unit.emitln(); - if( !customKeyClass ) { - emitJavaCallbackKeyClass(KeyClassName); - } if( !cfg.emittedJavaCallbackUserParamClasses.contains(fqUsrParamClassName) ) { - emitJavaCallbackUsrParamClass(UsrParamClassName); + emitJavaCallbackDataClass(capIfaceName, DataClassName); cfg.emittedJavaCallbackUserParamClasses.add(fqUsrParamClassName); } - unit.emitln(" private final java.util.Map<"+KeyClassName+", "+UsrParamClassName+"> "+usrMapInstanceName+" = new java.util.HashMap<"+KeyClassName+", "+UsrParamClassName+">();"); + if( useDataMap ) { + unit.emitln(" private final Map<"+KeyClassName+", "+DataClassName+"> "+dataMapInstanceName+" = new HashMap<"+KeyClassName+", "+DataClassName+">();"); + } else { + unit.emitln(" private "+DataClassName+" "+dataInstanceName+" = null;"); + } + unit.emitln(" private final Object "+lockInstanceName+" = new Object();"); unit.emitln(); } } @@ -768,8 +904,8 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { if( null != javaCallback ) { final String lowIfaceName = CodeGenUtils.decapitalizeString( getInterfaceName() ); - final String usrMapInstanceName = lowIfaceName+"UsrMap"; - unit.emitln(" synchronized( "+usrMapInstanceName+" ) {"); + final String lockInstanceName = lowIfaceName+"Lock"; + unit.emitln(" synchronized( "+lockInstanceName+" ) {"); unit.emitln(" final long[] nativeUserParam = { 0 };"); unit.emitln(); } @@ -806,18 +942,29 @@ public class JavaMethodBindingEmitter extends FunctionEmitter { if( null != javaCallback ) { final String funcArgName = binding.getArgumentName(javaCallback.setFuncCBParamIdx); final String userParamArgName = binding.getArgumentName(javaCallback.setFuncUserParamIdx); - final String UsrParamClassName = CodeGenUtils.capitalizeString( javaCallback.cbFuncTypeName+"UserParam" ); + final String DataClassName = CodeGenUtils.capitalizeString( javaCallback.cbFuncTypeName+"Data" ); + final boolean useDataMap = javaCallback.setFuncKeyIndices.size() > 0; + final String KeyClassName; + if( null != javaCallback.setFuncKeyClassName ) { + KeyClassName = javaCallback.setFuncKeyClassName; + } else { + KeyClassName = CodeGenUtils.capitalizeString(capIfaceName+"Key"); + } if( DEBUG_JAVACALLBACK ) { unit.emitln(" System.err.println(\"ZZZ returned nativeUserParam 0x\"+Long.toHexString(nativeUserParam[0]));"); } unit.emitln(); unit.emitln(" if( 0 != nativeUserParam[0] ) {"); unit.emitln(" // callback registrated -> add will release a previously mapped instance "); - unit.emitln(" add"+capIfaceName+"Map("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, true).toString()+ - "new "+UsrParamClassName+"("+funcArgName+", "+userParamArgName+", nativeUserParam[0]));"); + unit.emitln(" add"+capIfaceName+"("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, true).toString()+ + "new "+DataClassName+"("+funcArgName+", "+userParamArgName+", nativeUserParam[0]));"); unit.emitln(" } else {"); unit.emitln(" // callback released (null func) -> release a previously mapped instance "); - unit.emitln(" release"+capIfaceName+"Map("+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+");"); + if( useDataMap ) { + unit.emitln(" release"+capIfaceName+"( new "+KeyClassName+"( "+binding.getJavaCallSelectArguments(new StringBuilder(), javaCallback.setFuncKeyIndices, false).toString()+" ) );"); + } else { + unit.emitln(" release"+capIfaceName+"();"); + } unit.emitln(" }"); unit.emitln(" } // synchronized "); } diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java b/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java index e43d73e..badd299 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/Test4JavaCallback.java @@ -29,9 +29,11 @@ package com.jogamp.gluegen.test.junit.generation; import java.io.IOException; +import java.util.Set; import com.jogamp.common.os.NativeLibrary; import com.jogamp.gluegen.test.junit.generation.Bindingtest2.ALBUFFERCALLBACKTYPESOFT; +import com.jogamp.gluegen.test.junit.generation.Bindingtest2.AlBufferCallback0Key; import com.jogamp.gluegen.test.junit.generation.Bindingtest2.T2_CallbackFunc01; import com.jogamp.gluegen.test.junit.generation.impl.Bindingtest2Impl; @@ -214,6 +216,9 @@ public class Test4JavaCallback extends BaseClass { final int buffer1 = 1; final int buffer2 = 2; final int buffer3 = 3; + final AlBufferCallback0Key buffer1Key = new AlBufferCallback0Key(buffer1); + final AlBufferCallback0Key buffer2Key = new AlBufferCallback0Key(buffer2); + final AlBufferCallback0Key buffer3Key = new AlBufferCallback0Key(buffer3); final MyUserParam02 myUserParam01 = new MyUserParam02( 1); final MyUserParam02 myUserParam02 = new MyUserParam02( 2); Assert.assertEquals( 1, myUserParam01.i); @@ -223,33 +228,48 @@ public class Test4JavaCallback extends BaseClass { Assert.assertEquals( 0, myUserParam02.j); Assert.assertEquals( 0, myUserParam02.buffer); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(0, bt2.getAlBufferCallback0Keys().size()); // 1st mapping: buffer1 -> myCallback01, myUserParam01 bt2.alBufferCallback0(buffer1, 0, 0, myCallback01, myUserParam01); - Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(1, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } // 2nd mapping: buffer2 -> myCallback02, myUserParam02 bt2.alBufferCallback0(buffer2, 0, 0, myCallback02, myUserParam02); - Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1)); - Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1)); - Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback0UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1)); - Assert.assertEquals(myCallback02, bt2.getAlBufferCallback0(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(myCallback02, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(2, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(true, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } { bt2.alBufferCallback0Inject(buffer1, 10, 100); // buffer1 -> myCallback01, myUserParam01 @@ -274,15 +294,15 @@ public class Test4JavaCallback extends BaseClass { // Switch the callback function for buffer2 -> myCallback01, myUserParam02 bt2.alBufferCallback0(buffer2, 0, 0, myCallback01, myUserParam02); - Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1)); - Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1)); - Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback0UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); { bt2.alBufferCallback0Inject(buffer1, 11, 101); // buffer1 -> myCallback01, myUserParam01 @@ -307,27 +327,41 @@ public class Test4JavaCallback extends BaseClass { // Just release the buffer2 callback and mapped resources bt2.alBufferCallback0(buffer2, 0, 0, null, myUserParam02); // usrptr is not key, only buffer is key! - Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(1, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } // Just release the buffer1 callback and mapped resources bt2.alBufferCallback0(buffer1, 0, 0, null, null); // usrptr is not key, only buffer is key! - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(0, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(false, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } { bt2.alBufferCallback0Inject(buffer2, 1, 10); // unmapped, no change in data @@ -373,6 +407,9 @@ public class Test4JavaCallback extends BaseClass { final int buffer1 = 1; final int buffer2 = 2; final int buffer3 = 3; + final CustomAlBufferCallback1Key buffer1Key = new CustomAlBufferCallback1Key(buffer1); + final CustomAlBufferCallback1Key buffer2Key = new CustomAlBufferCallback1Key(buffer2); + final CustomAlBufferCallback1Key buffer3Key = new CustomAlBufferCallback1Key(buffer3); final MyUserParam02 myUserParam01 = new MyUserParam02( 1); final MyUserParam02 myUserParam02 = new MyUserParam02( 2); Assert.assertEquals( 1, myUserParam01.i); @@ -382,33 +419,48 @@ public class Test4JavaCallback extends BaseClass { Assert.assertEquals( 0, myUserParam02.j); Assert.assertEquals( 0, myUserParam02.buffer); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3Key)); + Assert.assertEquals(0, bt2.getAlBufferCallback1Keys().size()); // 1st mapping: buffer1 -> myCallback01, myUserParam01 bt2.alBufferCallback1(buffer1, 0, 0, myCallback01, myUserParam01); - Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3Key)); + Assert.assertEquals(1, bt2.getAlBufferCallback1Keys().size()); + { + final Set<CustomAlBufferCallback1Key> keys = bt2.getAlBufferCallback1Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } // 2nd mapping: buffer2 -> myCallback02, myUserParam02 bt2.alBufferCallback1(buffer2, 0, 0, myCallback02, myUserParam02); - Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1)); - Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1)); - Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback1UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1)); - Assert.assertEquals(myCallback02, bt2.getAlBufferCallback1(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1Key)); + Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1Key)); + Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback1UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1Key)); + Assert.assertEquals(myCallback02, bt2.getAlBufferCallback1(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3Key)); + Assert.assertEquals(2, bt2.getAlBufferCallback1Keys().size()); + { + final Set<CustomAlBufferCallback1Key> keys = bt2.getAlBufferCallback1Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(true, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } { bt2.alBufferCallback1Inject(buffer1, 10, 100); // buffer1 -> myCallback01, myUserParam01 @@ -433,15 +485,15 @@ public class Test4JavaCallback extends BaseClass { // Switch the callback function for buffer2 -> myCallback01, myUserParam02 bt2.alBufferCallback1(buffer2, 0, 0, myCallback01, myUserParam02); - Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1)); - Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1)); - Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback1UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1Key)); + Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1Key)); + Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback1UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3Key)); { bt2.alBufferCallback1Inject(buffer1, 11, 101); // buffer1 -> myCallback01, myUserParam01 @@ -466,27 +518,41 @@ public class Test4JavaCallback extends BaseClass { // Just release the buffer2 callback and mapped resources bt2.alBufferCallback1(buffer2, 0, 0, null, myUserParam02); // usrptr is not key, only buffer is key! - Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3)); - Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3)); - Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3)); + Assert.assertEquals(true, bt2.isAlBufferCallback1Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback1UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback1(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3Key)); + Assert.assertEquals(1, bt2.getAlBufferCallback1Keys().size()); + { + final Set<CustomAlBufferCallback1Key> keys = bt2.getAlBufferCallback1Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } // Just release the buffer1 callback and mapped resources bt2.alBufferCallback1(buffer1, 0, 0, null, null); // usrptr is not key, only buffer is key! - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer1)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2)); - Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer1)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer2)); - Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback1Mapped(buffer3Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1UserParam(buffer3Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback1(buffer3Key)); + Assert.assertEquals(0, bt2.getAlBufferCallback1Keys().size()); + { + final Set<CustomAlBufferCallback1Key> keys = bt2.getAlBufferCallback1Keys(); + Assert.assertEquals(false, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } { bt2.alBufferCallback1Inject(buffer2, 1, 10); // unmapped, no change in data @@ -521,6 +587,166 @@ public class Test4JavaCallback extends BaseClass { } } + /** + * Test in depth lifecycle of Bindingtest2 with ALBUFFERCALLBACKTYPESOFT JavaCallback via alBufferCallback1() + * using the default AlBufferCallback1Key class. + */ + @Test + public void chapter04() throws Exception { + final Bindingtest2 bt2 = new Bindingtest2Impl(); + + final long[] id_res = { -1 }; + final ALBUFFERCALLBACKTYPESOFT myCallback01 = new ALBUFFERCALLBACKTYPESOFT() { + @Override + public void callback(final int buffer, final Object userptr, final int sampledata, final int numbytes) { + final MyUserParam02 myUserParam = (MyUserParam02)userptr; + id_res[0] = sampledata + numbytes + myUserParam.i; + myUserParam.j = id_res[0]; + myUserParam.buffer = buffer; + System.err.println("chapter04.myCallback01: buffer "+buffer+", sampledata "+sampledata+", numbytes "+numbytes); + } + }; + final ALBUFFERCALLBACKTYPESOFT myCallback02 = new ALBUFFERCALLBACKTYPESOFT() { + @Override + public void callback(final int buffer, final Object userptr, final int sampledata, final int numbytes) { + final MyUserParam02 myUserParam = (MyUserParam02)userptr; + id_res[0] = sampledata * numbytes + myUserParam.i; + myUserParam.j = id_res[0]; + myUserParam.buffer = buffer; + System.err.println("chapter04.myCallback02: buffer "+buffer+", sampledata "+sampledata+", numbytes "+numbytes); + } + }; + final int buffer1 = 1; + final int buffer2 = 2; + final int buffer3 = 3; + final AlBufferCallback0Key buffer1Key = new AlBufferCallback0Key(buffer1); + final AlBufferCallback0Key buffer2Key = new AlBufferCallback0Key(buffer2); + final AlBufferCallback0Key buffer3Key = new AlBufferCallback0Key(buffer3); + final MyUserParam02 myUserParam01 = new MyUserParam02( 1); + final MyUserParam02 myUserParam02 = new MyUserParam02( 2); + Assert.assertEquals( 1, myUserParam01.i); + Assert.assertEquals( 0, myUserParam01.j); + Assert.assertEquals( 0, myUserParam01.buffer); + Assert.assertEquals( 2, myUserParam02.i); + Assert.assertEquals( 0, myUserParam02.j); + Assert.assertEquals( 0, myUserParam02.buffer); + + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(0, bt2.getAlBufferCallback0Keys().size()); + + // 1st mapping: buffer1 -> myCallback01, myUserParam01 + bt2.alBufferCallback0(buffer1, 0, 0, myCallback01, myUserParam01); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(1, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } + + // 2nd mapping: buffer2 -> myCallback02, myUserParam02 + bt2.alBufferCallback0(buffer2, 0, 0, myCallback02, myUserParam02); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(myUserParam02, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(myCallback02, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(2, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(true, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } + + { + bt2.alBufferCallback0Inject(buffer1, 10, 100); // buffer1 -> myCallback01, myUserParam01 + Assert.assertEquals(10+100+1, id_res[0]); + Assert.assertEquals( 1, myUserParam01.i); + Assert.assertEquals(10+100+1, myUserParam01.j); + Assert.assertEquals( 1, myUserParam01.buffer); + Assert.assertEquals( 2, myUserParam02.i); + Assert.assertEquals( 0, myUserParam02.j); + Assert.assertEquals( 0, myUserParam02.buffer); + } + { + bt2.alBufferCallback0Inject(buffer2, 10, 100); // buffer2 -> myCallback02, myUserParam02 + Assert.assertEquals(10*100+2, id_res[0]); + Assert.assertEquals( 1, myUserParam01.i); + Assert.assertEquals(10+100+1, myUserParam01.j); + Assert.assertEquals( 1, myUserParam01.buffer); + Assert.assertEquals( 2, myUserParam02.i); + Assert.assertEquals(10*100+2, myUserParam02.j); + Assert.assertEquals( 2, myUserParam02.buffer); + } + + // Just release the buffer2 callback and mapped resources + bt2.releaseAlBufferCallback0(buffer2Key); + // bt2.alBufferCallback0(buffer2, 0, 0, null, myUserParam02); // usrptr is not key, only buffer is key! + Assert.assertEquals(true, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(myUserParam01, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(myCallback01, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(1, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(true, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } + + // Just release the buffer1 callback and mapped resources + bt2.releaseAlBufferCallback0(buffer1Key); + // bt2.alBufferCallback0(buffer1, 0, 0, null, null); // usrptr is not key, only buffer is key! + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer1Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer2Key)); + Assert.assertEquals(false, bt2.isAlBufferCallback0Mapped(buffer3Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0UserParam(buffer3Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer1Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer2Key)); + Assert.assertEquals(null, bt2.getAlBufferCallback0(buffer3Key)); + Assert.assertEquals(0, bt2.getAlBufferCallback0Keys().size()); + { + final Set<AlBufferCallback0Key> keys = bt2.getAlBufferCallback0Keys(); + Assert.assertEquals(false, keys.contains(buffer1Key)); + Assert.assertEquals(false, keys.contains(buffer2Key)); + Assert.assertEquals(false, keys.contains(buffer3Key)); + } + + if( false ){ + bt2.alBufferCallback0Inject(buffer2, 1, 10); // unmapped, no change in data + Assert.assertEquals( 1+ 10+2, id_res[0]); + Assert.assertEquals( 1, myUserParam01.i); + Assert.assertEquals(11+101+1, myUserParam01.j); + Assert.assertEquals( 1, myUserParam01.buffer); + Assert.assertEquals( 2, myUserParam02.i); + Assert.assertEquals( 1+ 10+2, myUserParam02.j); + Assert.assertEquals( 2, myUserParam02.buffer); + } + } + public static class CustomAlBufferCallback1Key { private final int buffer; public CustomAlBufferCallback1Key(final int buffer) { diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg index de713cf..812676e 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test2.cfg @@ -62,10 +62,11 @@ ArgumentIsString InjectMessageCallback01 1 # # This callback has no keys defines, rendering it of global scope! # -# Explicit queries are generated, passing the keys as paramters +# Explicit maintenance methods are generated, passing the keys as paramters # - `boolean isMessageCallback01Mapped()` queries whether `MessageCallback0` is mapped globally # - `T2_CallbackFunc01 getMessageCallback01()` returns the global T2_CallbackFunc01, null if not mapped # - `Object getMessageCallback01UserParam()` returns the global `usrParam` object, null if not mapped +# - `void releaseMessageCallback01()` releases callback data skipping toolkit API. Favor passing `null` callback ref to `MessageCallback01(..)` JavaCallbackDef MessageCallback01 T2_CallbackFunc01 2 # # End JavaCallback @@ -87,10 +88,11 @@ ArgumentIsString alEventCallbackInject 3 # This callback has no keys defines, rendering it of global scope! # The global key-less scope matches `AL_SOFT_events` semantics. # -# Explicit queries are generated, passing the keys as paramters +# Explicit maintenance methods are generated, passing the keys as paramters # - `boolean isAlEventCallbackMapped()` queries whether `alEventCallback` is mapped globally # - `ALEVENTPROCSOFT getAlEventCallback()` returns the global ALEVENTPROCSOFT, null if not mapped # - `Object getAlEventCallbackUserParam()` returns the global `userParam` object, null if not mapped +# - `void releaseAlEventCallback()` releases callback data skipping toolkit API. Favor passing `null` callback ref to `alEventCallback(..)` JavaCallbackDef alEventCallback ALEVENTPROCSOFT 5 JavaCallbackKey alEventCallback # @@ -115,10 +117,13 @@ JavaCallbackKey alEventCallback # This callback defines one key, `buffer`, index 0 of alBufferCallback0(..) parameter list, limiting it to buffer-name scope! # The `buffer` key allows setting one callback per buffer-name, compatible with the `AL_SOFT_callback_buffer` spec. # -# Explicit queries are generated, passing the keys as paramters -# - `boolean isAlBufferCallback0Mapped(int buffer)` queries whether `alBufferCallback0` is mapped to `buffer`. -# - `ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(int buffer)` returns the `buffer` mapped ALEVENTPROCSOFT, null if not mapped -# - `Object getAlBufferCallback0UserParam(int buffer)` returns the `buffer` mapped `userptr` object, null if not mapped +# Explicit maintenance methods are generated, passing the keys as paramters +# - `Set<AlBufferCallback0Key> getAlBufferCallback0Keys()` returns set of Key { int buffer } +# - `boolean isAlBufferCallback0Mapped(AlBufferCallback0Key)` queries whether `alBufferCallback0` is mapped to `buffer`. +# - `ALBUFFERCALLBACKTYPESOFT getAlBufferCallback0(AlBufferCallback0Key)` returns the `buffer` mapped ALEVENTPROCSOFT, null if not mapped +# - `Object getAlBufferCallback0UserParam(AlBufferCallback0Key)` returns the `buffer` mapped `userptr` object, null if not mapped +# - `void releaseAllAlBufferCallback0()` releases all callback data mapped via Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to `alBufferCallback0(..)` +# - `void releaseAlBufferCallback0(AlBufferCallback0Key)` releases callback data mapped to Key { int buffer } skipping toolkit API. Favor passing `null` callback ref to `alBufferCallback0(..)` JavaCallbackDef alBufferCallback0 ALBUFFERCALLBACKTYPESOFT 1 JavaCallbackKey alBufferCallback0 0 # @@ -142,7 +147,7 @@ JavaCallbackKey alBufferCallback0 0 # This callback defines one key, `buffer`, index 0 of alBufferCallback1(..) parameter list, limiting it to buffer-name scope! # The `buffer` key allows setting one callback per buffer-name, compatible with the `AL_SOFT_callback_buffer` spec. # -# Explicit queries are generated, passing the keys as paramters +# Explicit maintenance methods are generated, passing the keys as paramters # - `boolean isAlBufferCallback1Mapped(int buffer)` queries whether `alBufferCallback1` is mapped to `buffer`. # - `ALBUFFERCALLBACKTYPESOFT getAlBufferCallback1(int buffer)` returns the `buffer` mapped ALEVENTPROCSOFT, null if not mapped # - `Object getAlBufferCallback1UserParam(int buffer)` returns the `buffer` mapped `userptr` object, null if not mapped |