Skip to content

Commit

Permalink
* Add new @CriticalRegion annotation to allow zero-copy access to …
Browse files Browse the repository at this point in the history
…data of Java arrays (pull #254)
  • Loading branch information
vincent-grosbois authored and saudet committed Aug 25, 2018
1 parent fa35503 commit c50d69f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Add new `@CriticalRegion` annotation to allow zero-copy access to data of Java arrays ([pull #254](https://github.com/bytedeco/javacpp/pull/254))
* Allow `Builder` to create links for resource libraries even when no Java classes are built
* Fix `Loader.cacheResource()` creating a subdirectory named "null" when caching a top-level file
* Update `README.md` with reference to newly published [Mapping Recipes for C/C++ Libraries](https://github.com/bytedeco/javacpp/wiki/Mapping-Recipes)
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/bytedeco/javacpp/annotation/CriticalRegion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.bytedeco.javacpp.annotation;

import org.bytedeco.javacpp.tools.Generator;

import java.lang.annotation.*;

/**
* In some methods, {@link Generator} will generate code to transfer arrays from the
* JVM to native code using the {@code Get/Release<primitivetype>ArrayElements} methods.
* However these methods copy the underlying data. With this annotation, the generated
* code will always call the {@code Get/ReleasePrimitiveArrayCritical} methods instead.
*
* @see Generator
*
*/
@Documented @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface CriticalRegion { }
23 changes: 21 additions & 2 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.bytedeco.javacpp.annotation.Cast;
import org.bytedeco.javacpp.annotation.Const;
import org.bytedeco.javacpp.annotation.Convention;
import org.bytedeco.javacpp.annotation.CriticalRegion;
import org.bytedeco.javacpp.annotation.Function;
import org.bytedeco.javacpp.annotation.Index;
import org.bytedeco.javacpp.annotation.MemberGetter;
Expand Down Expand Up @@ -113,6 +114,7 @@
* @see Cast
* @see Const
* @see Convention
* @see CriticalRegion
* @see Function
* @see Index
* @see MemberGetter
Expand Down Expand Up @@ -1871,7 +1873,7 @@ void parametersBefore(MethodInformation methodInfo) {
methodInfo.parameterTypes[j].getComponentType().isPrimitive()) {
out.print("arg" + j + " == NULL ? NULL : ");
String s = methodInfo.parameterTypes[j].getComponentType().getName();
if (methodInfo.valueGetter || methodInfo.valueSetter ||
if (methodInfo.criticalRegion || methodInfo.valueGetter || methodInfo.valueSetter ||
methodInfo.memberGetter || methodInfo.memberSetter) {
out.println("(j" + s + "*)env->GetPrimitiveArrayCritical(arg" + j + ", NULL);");
} else {
Expand Down Expand Up @@ -2502,7 +2504,7 @@ void parametersAfter(MethodInformation methodInfo) {
out.println(" }");
}
out.print(" if (arg" + j + " != NULL) ");
if (methodInfo.valueGetter || methodInfo.valueSetter ||
if (methodInfo.criticalRegion || methodInfo.valueGetter || methodInfo.valueSetter ||
methodInfo.memberGetter || methodInfo.memberSetter) {
out.println("env->ReleasePrimitiveArrayCritical(arg" + j + ", ptr" + j + ", " + releaseArrayFlag + ");");
} else {
Expand Down Expand Up @@ -3053,6 +3055,7 @@ MethodInformation methodInformation(Method method) {
info.dim = index != null ? index.value() : 0;
info.parameterTypes = method.getParameterTypes();
info.parameterAnnotations = method.getParameterAnnotations();
info.criticalRegion = criticalRegion(info.cls, info.method);
info.returnRaw = method.isAnnotationPresent(Raw.class);
info.withEnv = info.returnRaw ? method.getAnnotation(Raw.class).withEnv() : false;
info.parameterRaw = new boolean[info.parameterAnnotations.length];
Expand Down Expand Up @@ -3253,6 +3256,22 @@ MethodInformation methodInformation(Method method) {
return info;
}

static boolean criticalRegion(Class<?> cls, Method method) {
boolean criticalRegion = baseClasses.contains(cls) ||
method.isAnnotationPresent(CriticalRegion.class);
while (!criticalRegion && cls != null) {
if (criticalRegion = cls.isAnnotationPresent(CriticalRegion.class)) {
break;
}
if (cls.getEnclosingClass() != null) {
cls = cls.getEnclosingClass();
} else {
cls = cls.getSuperclass();
}
}
return criticalRegion;
}

static boolean noException(Class<?> cls, Method method) {
boolean noException = baseClasses.contains(cls) ||
method.isAnnotationPresent(NoException.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class MethodInformation {
boolean[] parameterRaw;
Class<?>[] parameterTypes;
Annotation[][] parameterAnnotations;
boolean returnRaw, withEnv, overloaded, noOffset, deallocator, allocator, arrayAllocator,
boolean criticalRegion, returnRaw, withEnv, overloaded, noOffset, deallocator, allocator, arrayAllocator,
bufferGetter, valueGetter, valueSetter, memberGetter, memberSetter, noReturnGetter;
Method pairedMethod;
Class<?> throwsException;
Expand Down

0 comments on commit c50d69f

Please sign in to comment.