CL: Cleaned-up callbacks and object registries.

Mapped: Added .capacity() and .foreach() with default elementCount.
This commit is contained in:
Ioannis Tsakpinis 2011-08-02 23:45:19 +00:00
parent 83c2208aa0
commit f3472da2ed
17 changed files with 164 additions and 171 deletions

View File

@ -31,24 +31,39 @@
*/
package org.lwjgl.opencl;
import org.lwjgl.PointerWrapperAbstract;
/**
* Instances of this class can be used to receive OpenCL program build notifications.
* A single CLBuildProgramCallback instance should only be used with programs created
* in the same CLContext.
*
* @author Spasi
*/
public abstract class CLBuildProgramCallback extends CLCallback {
public abstract class CLBuildProgramCallback extends PointerWrapperAbstract {
private CLContext context;
protected CLBuildProgramCallback() {
super(CallbackUtil.getBuildProgramCallback());
}
/**
* Sets the context that contains the CLPrograms to which we're registered.
*
* @param context the CLContext object
*/
void setContext(final CLContext context) {
this.context = context;
}
/**
* Called from native code.
*
* @param program_address the CLProgram object pointer
*/
private void handleMessage(long program_address) {
handleMessage(CLContext.getCLProgramGlobal(program_address));
handleMessage(context.getCLProgram(program_address));
}
/**

View File

@ -1,59 +0,0 @@
/*
* Copyright (c) 2002-2010 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.opencl;
import org.lwjgl.PointerWrapperAbstract;
/**
* Base class for OpenCL callback objects.
*
* @author Spasi
*/
abstract class CLCallback extends PointerWrapperAbstract {
private final boolean custom;
protected CLCallback(final long pointer) {
this(pointer, false);
}
protected CLCallback(final long pointer, final boolean custom) {
super(pointer);
this.custom = custom;
}
final boolean isCustom() {
return custom;
}
}

View File

@ -50,7 +50,7 @@ public final class CLCommandQueue extends CLObjectChild<CLContext> {
super(pointer, context);
if ( isValid() ) {
this.device = device;
this.clEvents = new CLObjectRegistryGlobal<CLEvent>(CLContext.clEventsGlobal);
this.clEvents = new CLObjectRegistry<CLEvent>();
context.getCLCommandQueueRegistry().registerObject(this);
} else {
this.device = null;

View File

@ -54,12 +54,6 @@ public final class CLContext extends CLObjectChild<CLPlatform> {
private final CLObjectRegistry<CLProgram> clPrograms;
private final CLObjectRegistry<CLEvent> clEvents;
/** Global registry for build callbacks. */
static final FastLongMap<CLProgram> clProgramsGlobal = new FastLongMap<CLProgram>();
/** Global registry for event callbacks. */
static final FastLongMap<CLEvent> clEventsGlobal = new FastLongMap<CLEvent>();
CLContext(final long pointer, final CLPlatform platform) {
super(pointer, platform);
@ -70,8 +64,8 @@ public final class CLContext extends CLObjectChild<CLPlatform> {
clCommandQueues = new CLObjectRegistry<CLCommandQueue>();
clMems = new CLObjectRegistry<CLMem>();
clSamplers = new CLObjectRegistry<CLSampler>();
clPrograms = new CLObjectRegistryGlobal<CLProgram>(clProgramsGlobal);
clEvents = new CLObjectRegistryGlobal<CLEvent>(clEventsGlobal);
clPrograms = new CLObjectRegistry<CLProgram>();
clEvents = new CLObjectRegistry<CLEvent>();
} else {
clCommandQueues = null;
clMems = null;
@ -275,8 +269,4 @@ public final class CLContext extends CLObjectChild<CLPlatform> {
CLObjectRegistry<CLEvent> getCLEventRegistry() { return clEvents; }
static CLProgram getCLProgramGlobal(final long id) { return clProgramsGlobal.get(id); }
static CLEvent getCLEventGlobal(final long id) { return clEventsGlobal.get(id); }
}

View File

@ -108,6 +108,13 @@ public final class CLEvent extends CLObjectChild<CLContext> {
// -------[ IMPLEMENTATION STUFF BELOW ]-------
CLObjectRegistry<CLEvent> getParentRegistry() {
if ( queue == null )
return getParent().getCLEventRegistry();
else
return queue.getCLEventRegistry();
}
int release() {
try {
return super.release();

View File

@ -31,30 +31,46 @@
*/
package org.lwjgl.opencl;
import org.lwjgl.PointerWrapperAbstract;
/**
* Instances of this class can be used to receive OpenCL memory object destruction notifications.
* Instances of this class can be used to handle OpenCL event callbacks. A single
* CLEventCallback instance should only be used on events generated from the same
* CLCommandQueue or on user events associated with the same CLContext.
*
* @author Spasi
*/
public abstract class CLEventCallback extends CLCallback {
public abstract class CLEventCallback extends PointerWrapperAbstract {
private CLObjectRegistry<CLEvent> eventRegistry;
protected CLEventCallback() {
super(CallbackUtil.getEventCallback());
}
/**
* Sets the eventRegistry that contains the CLEvents to which we're registered.
*
* @param eventRegistry the CLEvent object registry
*/
void setRegistry(final CLObjectRegistry<CLEvent> eventRegistry) {
this.eventRegistry = eventRegistry;
}
/**
* Called from native code.
*
* @param event_address the CLEvent object pointer
*/
private void handleMessage(long event_address, int event_command_exec_status) {
handleMessage(CLContext.getCLEventGlobal(event_address), event_command_exec_status);
handleMessage(eventRegistry.getObject(event_address), event_command_exec_status);
}
/**
* The callback method.
*
* @param event the CLEvent object
* @param event the CLEvent object
* @param event_command_exec_status the execution status
*/
protected abstract void handleMessage(CLEvent event, int event_command_exec_status);

View File

@ -31,12 +31,14 @@
*/
package org.lwjgl.opencl;
import org.lwjgl.PointerWrapperAbstract;
/**
* Instances of this class can be used to receive OpenCL memory object destruction notifications.
*
* @author Spasi
*/
public abstract class CLMemObjectDestructorCallback extends CLCallback {
public abstract class CLMemObjectDestructorCallback extends PointerWrapperAbstract {
protected CLMemObjectDestructorCallback() {
super(CallbackUtil.getMemObjectDestructorCallback());

View File

@ -31,6 +31,8 @@
*/
package org.lwjgl.opencl;
import org.lwjgl.PointerWrapperAbstract;
import java.nio.ByteBuffer;
/**
@ -43,7 +45,7 @@ import java.nio.ByteBuffer;
* @see CL10#clEnqueueNativeKernel
* @see #execute(java.nio.ByteBuffer[])
*/
public abstract class CLNativeKernel extends CLCallback {
public abstract class CLNativeKernel extends PointerWrapperAbstract {
protected CLNativeKernel() {
super(CallbackUtil.getNativeKernelCallback());

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2002-2010 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.lwjgl.opencl;
/**
* A CLObject registry that also registers/unregisters objects to/from a global registry.
*
* @author Spasi
*/
final class CLObjectRegistryGlobal<T extends CLObjectChild> extends CLObjectRegistry<T> {
private final FastLongMap<T> globalRegistry;
CLObjectRegistryGlobal(final FastLongMap<T> globalRegistry) {
this.globalRegistry = globalRegistry;
}
void registerObject(final T object) {
super.registerObject(object);
globalRegistry.put(object.getPointer(), object);
}
void unregisterObject(final T object) {
super.unregisterObject(object);
globalRegistry.remove(object.getPointerUnsafe());
}
}

View File

@ -53,9 +53,6 @@ public final class CLPlatform extends CLObject {
private final CLObjectRegistry<CLDevice> clDevices;
/** Global registry for build callbacks. */
static final FastLongMap<CLDevice> clDevicesGlobal = new FastLongMap<CLDevice>();
private Object caps;
CLPlatform(final long pointer) {
@ -63,7 +60,7 @@ public final class CLPlatform extends CLObject {
if ( isValid() ) {
clPlatforms.put(pointer, this);
clDevices = new CLObjectRegistryGlobal<CLDevice>(clDevicesGlobal);
clDevices = new CLObjectRegistry<CLDevice>();
} else
clDevices = null;
}
@ -195,8 +192,6 @@ public final class CLPlatform extends CLObject {
CLObjectRegistry<CLDevice> getCLDeviceRegistry() { return clDevices; }
static CLDevice getCLDeviceGlobal(final long id) { return clDevicesGlobal.get(id); }
/**
* Called from <code>clGetDeviceIDs</code> to register new devices.
*

View File

@ -55,13 +55,20 @@ public class MappedObjectTests1 {
ByteBuffer bb = ByteBuffer.allocateDirect(200);
MappedFloat vecs = MappedFloat.map(bb);
// verify 'malloc' and SIZEOF
// verify 'malloc', SIZEOF and capacity()
{
MappedFloat vecs1 = MappedFloat.malloc(1234);
assert (vecs1.getSizeof() == MappedFloat.SIZEOF);
assert (vecs1.getSizeof() * 1234 == vecs1.backingByteBuffer().capacity());
assert (MappedFloat.SIZEOF * 1234 == vecs1.backingByteBuffer().capacity());
assert(vecs1.capacity() == vecs1.backingByteBuffer().capacity() / MappedFloat.SIZEOF);
ByteBuffer buf = ByteBuffer.allocateDirect(200);
buf.position(10 * MappedFloat.SIZEOF);
MappedFloat vecs2 = MappedFloat.map(buf);
assert(vecs2.capacity() == (vecs2.backingByteBuffer().capacity() / MappedFloat.SIZEOF) - 10);
}
// manipulate 'mapped.value'

View File

@ -70,15 +70,21 @@ public class MappedObjectTests3 {
}
static void testForeach() {
int elementCount = 4;
int elementCount = 10;
MappedSomething some = MappedSomething.malloc(elementCount);
int i = 0;
for ( MappedSomething item : foreach(some, elementCount) ) {
for ( MappedSomething item : foreach(some, elementCount / 2) ) {
assert (item.view == i++);
}
assert (some.view != elementCount);
System.out.println("current.view=" + some.view + ", not " + elementCount + ", as you might expect");
assert (some.view == (elementCount / 2) - 1);
System.out.println("current.view=" + some.view + ", not " + (elementCount / 2) + ", as you might expect");
i = 0;
for ( MappedSomething item : foreach(some) ) {
assert (item.view == i++);
}
assert (some.view == elementCount - 1);
}
public static class Xyz extends MappedObject {

View File

@ -143,23 +143,41 @@ public class HelloOpenCL {
System.out.println("-TRYING TO EXEC NATIVE KERNEL-");
final CLCommandQueue queue = clCreateCommandQueue(context, device, 0, null);
final PointerBuffer ev = BufferUtils.createPointerBuffer(1);
clEnqueueNativeKernel(queue, new CLNativeKernel() {
protected void execute(final ByteBuffer[] memobjs) {
if ( memobjs == null )
System.out.println("OK, it's null");
else {
System.out.println("memobjs = " + memobjs.length);
for ( int k = 0; k < memobjs.length; k++ ) {
System.out.println("memobjs[" + k + "].remaining() = " + memobjs[k].remaining());
for ( int l = memobjs[k].position(); l < memobjs[k].limit(); l++ ) {
memobjs[k].put(l, (byte)l);
}
System.out.println("\tmemobjs.length = " + memobjs.length);
for ( int k = 0; k < memobjs.length; k++ ) {
System.out.println("\tmemobjs[" + k + "].remaining() = " + memobjs[k].remaining());
for ( int l = memobjs[k].position(); l < memobjs[k].limit(); l++ ) {
memobjs[k].put(l, (byte)l);
}
}
System.out.println("\tNative kernel done.");
}
}, new CLMem[] { buffer }, new long[] { 128 }, null, null);
}, new CLMem[] { buffer }, new long[] { 128 }, null, ev);
clFinish(queue);
final CLEvent e = queue.getCLEvent(ev.get(0));
clSetEventCallback(e, CL_COMPLETE, new CLEventCallback() {
protected void handleMessage(final CLEvent event, final int event_command_exec_status) {
System.out.println("\t\tEvent callback status: " + getEventStatusName(event_command_exec_status));
}
});
int status = e.getInfoInt(CL_EVENT_COMMAND_EXECUTION_STATUS);
System.out.println("NATIVE KERNEL STATUS: " + getEventStatusName(status));
clFlush(queue);
do {
int newStatus = e.getInfoInt(CL_EVENT_COMMAND_EXECUTION_STATUS);
if ( newStatus != status ) {
status = newStatus;
System.out.println("NATIVE KERNEL STATUS: " + getEventStatusName(status));
}
} while ( status != CL_SUCCESS ); // Busy-spin until we're done
clReleaseEvent(e);
}
}
@ -182,6 +200,19 @@ public class HelloOpenCL {
System.out.println("\t" + param_name + " = " + device.getInfoString(param));
}
private static String getEventStatusName(final int status) {
switch ( status ) {
case CL_QUEUED:
return "CL_QUEUED";
case CL_SUBMITTED:
return "CL_SUBMITTED";
case CL_RUNNING:
return "CL_RUNNING";
default:
return "CL_COMPLETE";
}
}
private static void die(String kind, String description) {
System.out.println(kind + " error " + description + " occured");
}

View File

@ -132,6 +132,16 @@ public abstract class MappedObject {
throw new InternalError("type not registered");
}
/**
* Returns the number of mapped objects that fit in the mapped buffer.
*
* @return the mapped object capacity
*/
public final int capacity() {
// No call-site modification for this, we override in every subclass instead.
throw new InternalError("type not registered");
}
/**
* Creates a MappedObject instance, mapping the memory region of the specified direct ByteBuffer.
* <p/>
@ -200,7 +210,7 @@ public abstract class MappedObject {
/**
* Any code in the default constructor will not run automatically. This method
* can be used to run execute that code on the current view.
* can be used to execute that code on the current view.
*/
public final void runViewConstructor() {
// any method that calls this method will have its call-site modified
@ -235,6 +245,18 @@ public abstract class MappedObject {
throw new InternalError("type not registered");
}
/**
* Creates an {@link Iterable} <MappedObject> that will step through
* <code>capacity()</code> views, leaving the <code>view</code> at
* the last valid value.<br>
* <p/>
* For convenience you are encouraged to static-import this specific method:
* <code>import static org.lwjgl.util.mapped.MappedObject.foreach;</code>
*/
public static <T extends MappedObject> Iterable<T> foreach(T mapped) {
return foreach(mapped, mapped.capacity());
}
/**
* Creates an {@link Iterable} <MappedObject> that will step through
* <code>elementCount</code> views, leaving the <code>view</code> at

View File

@ -32,6 +32,7 @@
package org.lwjgl.util.mapped;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.MemoryUtil;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.*;
@ -42,6 +43,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
@ -82,9 +84,9 @@ public class MappedObjectTransformer {
static final String NEXT_METHOD_NAME = "next";
static final String ALIGN_METHOD_NAME = "getAlign";
static final String SIZEOF_METHOD_NAME = "getSizeof";
static final String CAPACITY_METHOD_NAME = "capacity"; // Used for .asArray().length
// Internal methods
static final String LENGTH_METHOD_NAME = "length$LWJGL"; // Used for .asArray().length
static final String VIEW_CONSTRUCTOR_NAME = "constructView$LWJGL"; // Used by runViewConstructor
static final Map<Integer, String> OPCODE_TO_NAME = new HashMap<Integer, String>();
@ -228,6 +230,7 @@ public class MappedObjectTransformer {
NEXT_METHOD_NAME,
ALIGN_METHOD_NAME,
SIZEOF_METHOD_NAME,
CAPACITY_METHOD_NAME,
};
public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature, final String[] exceptions) {
@ -285,7 +288,7 @@ public class MappedObjectTransformer {
final MappedSubtypeInfo mappedSubtype = className_to_subtype.get(className);
generateViewAddressGetter();
generateLengthGetter();
generateCapacity();
generateAlignGetter(mappedSubtype);
generateSizeofGetter();
generateNext();
@ -329,16 +332,25 @@ public class MappedObjectTransformer {
mv.visitEnd();
}
private void generateLengthGetter() {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_STATIC, LENGTH_METHOD_NAME, "(L" + className + ";)I", null, null);
private void generateCapacity() {
// return (backingByteBuffer().capacity() + (int)(MemoryUtil.getAddress0(backingByteBuffer()) - baseAddress)) / SIZEOF;
MethodVisitor mv = super.visitMethod(ACC_PUBLIC, CAPACITY_METHOD_NAME, "()I", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, MAPPED_OBJECT_JVM, "backingByteBuffer", "()L" + jvmClassName(ByteBuffer.class) + ";");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKEVIRTUAL, jvmClassName(ByteBuffer.class), "capacity", "()I");
mv.visitInsn(SWAP);
mv.visitMethodInsn(INVOKESTATIC, jvmClassName(MemoryUtil.class), "getAddress0", "(L" + jvmClassName(Buffer.class) + ";)J");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, MAPPED_OBJECT_JVM, "baseAddress", "J");
mv.visitInsn(LSUB);
mv.visitInsn(L2I);
mv.visitInsn(IADD);
mv.visitFieldInsn(GETSTATIC, className, "SIZEOF", "I");
mv.visitInsn(IDIV);
mv.visitInsn(IRETURN);
mv.visitMaxs(2, 1);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
@ -1037,7 +1049,7 @@ public class MappedObjectTransformer {
instructions.remove(nextInsn);
loadInsn.var = var;
instructions.insert(loadInsn, new MethodInsnNode(INVOKESTATIC, mappedSubtype.className, LENGTH_METHOD_NAME, "(L" + mappedSubtype.className + ";)I"));
instructions.insert(loadInsn, new MethodInsnNode(INVOKEVIRTUAL, mappedSubtype.className, CAPACITY_METHOD_NAME, "()I"));
return i + 1;
} else if ( stackSize < loadStackSize ) // Consumed by something other than AALOAD or ARRAYLENGTH

View File

@ -432,7 +432,7 @@ public interface CL10 {
@Code(
tryBlock = true,
// Create a GlobalRef to the callback object.
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
javaBeforeNative = "\t\tlong user_data = pfn_notify == null || pfn_notify.isCustom() ? 0 : CallbackUtil.createGlobalRef(pfn_notify);",
// Associate context with the GlobalRef, so we can delete it later.
javaFinally = "\t\t\tCallbackUtil.registerCallback(__result, user_data);"
)
@ -845,7 +845,8 @@ public interface CL10 {
@Code(
tryBlock = true,
// Create a GlobalRef to the callback object.
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
"\t\tif ( pfn_notify != null ) pfn_notify.setContext(program.getParent());",
// Check if we need to delete the GlobalRef.
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
)
@ -861,7 +862,8 @@ public interface CL10 {
@Code(
tryBlock = true,
// Create a GlobalRef to the callback object.
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
"\t\tif ( pfn_notify != null ) pfn_notify.setContext(program.getParent());",
// Check if we need to delete the GlobalRef.
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
)
@ -877,7 +879,8 @@ public interface CL10 {
@Code(
tryBlock = true,
// Create a GlobalRef to the callback object.
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
"\t\tif ( pfn_notify != null ) pfn_notify.setContext(program.getParent());",
// Check if we need to delete the GlobalRef.
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
)

View File

@ -190,7 +190,8 @@ public interface CL11 {
@Code(
tryBlock = true,
// Create a GlobalRef to the callback object.
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);",
javaBeforeNative = "\t\tlong user_data = CallbackUtil.createGlobalRef(pfn_notify);\n" +
"\t\tpfn_notify.setRegistry(event.getParentRegistry());",
// Check if we need to delete the GlobalRef.
javaFinally = "\t\t\tCallbackUtil.checkCallback(__result, user_data);"
)