Commit 9996b441 authored by Jacob Potter's avatar Jacob Potter

Avoid calling JNI during critical section. Fixes #76

parent 249b6174
...@@ -151,12 +151,39 @@ namespace djinni ...@@ -151,12 +151,39 @@ namespace djinni
static CppType toCpp(JNIEnv* jniEnv, JniType j) static CppType toCpp(JNIEnv* jniEnv, JniType j)
{ {
assert(j != nullptr); assert(j != nullptr);
auto deleter = [jniEnv, j] (void* c) { jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT); };
std::unique_ptr<uint8_t, decltype(deleter)> ptr(reinterpret_cast<uint8_t*>(jniEnv->GetPrimitiveArrayCritical(j, nullptr)), std::vector<uint8_t> ret;
deleter); jsize length = jniEnv->GetArrayLength(j);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return {ptr.get(), ptr.get() + jniEnv->GetArrayLength(j)};
if (!length) {
return {};
}
{
auto deleter = [jniEnv, j] (void* c) {
if (c) {
jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT);
}
};
std::unique_ptr<uint8_t, decltype(deleter)> ptr(
reinterpret_cast<uint8_t*>(jniEnv->GetPrimitiveArrayCritical(j, nullptr)),
deleter
);
if (ptr) {
// Construct and then move-assign. This copies the elements only once,
// and avoids having to initialize before filling (as with resize())
ret = std::vector<uint8_t>{ptr.get(), ptr.get() + length};
} else {
// Something failed...
jniExceptionCheck(jniEnv);
}
}
return ret;
} }
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
......
...@@ -30,4 +30,6 @@ test_helpers = interface +c { ...@@ -30,4 +30,6 @@ test_helpers = interface +c {
# Ensures that we generate integer translation code # Ensures that we generate integer translation code
static assorted_integers_id(i: assorted_integers): assorted_integers; static assorted_integers_id(i: assorted_integers): assorted_integers;
static id_binary(b: binary): binary;
} }
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector>
class ClientInterface; class ClientInterface;
class Token; class Token;
...@@ -66,4 +67,6 @@ public: ...@@ -66,4 +67,6 @@ public:
/** Ensures that we generate integer translation code */ /** Ensures that we generate integer translation code */
static AssortedIntegers assorted_integers_id(const AssortedIntegers & i); static AssortedIntegers assorted_integers_id(const AssortedIntegers & i);
static std::vector<uint8_t> id_binary(const std::vector<uint8_t> & b);
}; };
...@@ -52,6 +52,8 @@ public abstract class TestHelpers { ...@@ -52,6 +52,8 @@ public abstract class TestHelpers {
/** Ensures that we generate integer translation code */ /** Ensures that we generate integer translation code */
public static native AssortedIntegers assortedIntegersId(AssortedIntegers i); public static native AssortedIntegers assortedIntegersId(AssortedIntegers i);
public static native byte[] idBinary(byte[] b);
public static final class CppProxy extends TestHelpers public static final class CppProxy extends TestHelpers
{ {
private final long nativeRef; private final long nativeRef;
......
...@@ -220,4 +220,13 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_assortedInte ...@@ -220,4 +220,13 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_assortedInte
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
} }
CJNIEXPORT jbyteArray JNICALL Java_com_dropbox_djinni_test_TestHelpers_idBinary(JNIEnv* jniEnv, jobject /*this*/, jbyteArray j_b)
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
auto r = ::TestHelpers::id_binary(::djinni::Binary::toCpp(jniEnv, j_b));
return ::djinni::Binary::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
} // namespace djinni_generated } // namespace djinni_generated
...@@ -202,4 +202,11 @@ auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType ...@@ -202,4 +202,11 @@ auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType
} DJINNI_TRANSLATE_EXCEPTIONS() } DJINNI_TRANSLATE_EXCEPTIONS()
} }
+ (nonnull NSData *)idBinary:(nonnull NSData *)b {
try {
auto r = ::TestHelpers::id_binary(::djinni::Binary::toCpp(b));
return ::djinni::Binary::fromCpp(r);
} DJINNI_TRANSLATE_EXCEPTIONS()
}
@end @end
...@@ -59,4 +59,6 @@ ...@@ -59,4 +59,6 @@
/** Ensures that we generate integer translation code */ /** Ensures that we generate integer translation code */
+ (nonnull DBAssortedIntegers *)assortedIntegersId:(nonnull DBAssortedIntegers *)i; + (nonnull DBAssortedIntegers *)assortedIntegersId:(nonnull DBAssortedIntegers *)i;
+ (nonnull NSData *)idBinary:(nonnull NSData *)b;
@end @end
...@@ -130,3 +130,7 @@ void TestHelpers::check_enum(color) {} // stub ...@@ -130,3 +130,7 @@ void TestHelpers::check_enum(color) {} // stub
AssortedIntegers TestHelpers::assorted_integers_id(const AssortedIntegers & i) { AssortedIntegers TestHelpers::assorted_integers_id(const AssortedIntegers & i) {
return i; return i;
} }
std::vector<uint8_t> TestHelpers::id_binary(const std::vector<uint8_t> & v) {
return v;
}
...@@ -3,6 +3,7 @@ package com.dropbox.djinni.test; ...@@ -3,6 +3,7 @@ package com.dropbox.djinni.test;
import junit.framework.TestCase; import junit.framework.TestCase;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
public class PrimitiveListTest extends TestCase { public class PrimitiveListTest extends TestCase {
...@@ -27,4 +28,10 @@ public class PrimitiveListTest extends TestCase { ...@@ -27,4 +28,10 @@ public class PrimitiveListTest extends TestCase {
PrimitiveList converted = TestHelpers.getPrimitiveList(); PrimitiveList converted = TestHelpers.getPrimitiveList();
assertEquals(converted.getList(), jPrimitiveList.getList()); assertEquals(converted.getList(), jPrimitiveList.getList());
} }
public void testBinary()
{
byte[] b = { 1, 2, 3 };
assertTrue(Arrays.equals(TestHelpers.idBinary(b), b));
}
} }
...@@ -11,8 +11,9 @@ ...@@ -11,8 +11,9 @@
<src path="../generated-src"/> <src path="../generated-src"/>
<src path="../handwritten-src"/> <src path="../handwritten-src"/>
</javac> </javac>
<java classname="org.junit.runner.JUnitCore"> <java classname="org.junit.runner.JUnitCore" fork="true">
<classpath path="hamcrest-core-1.3.jar:junit-4.11.jar:classes"/> <classpath path="hamcrest-core-1.3.jar:junit-4.11.jar:classes"/>
<jvmarg value="-Xcheck:jni"/>
<arg value="com.dropbox.djinni.test.AllTests"/> <arg value="com.dropbox.djinni.test.AllTests"/>
</java> </java>
</target> </target>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment