Skip to content

Commit

Permalink
* Use thread local in Generator to detach automatically native thr…
Browse files Browse the repository at this point in the history
…eads on exit for Windows as well (pull #562)
  • Loading branch information
masterav10 authored Mar 15, 2022
1 parent 8d0547b commit e8aacb2
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Use thread local in `Generator` to detach automatically native threads on exit for Windows as well ([pull #562](https://github.com/bytedeco/javacpp/pull/562))
* Add compiler options for C++14 and C++17 to platform properties files for Visual Studio
* Fix `Parser` incorrectly shortening type names for nested class template instances
* Make `Parser` output `boolean has_value()` methods for basic containers like `std::optional`
Expand Down
24 changes: 20 additions & 4 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,16 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
out.println(" va_end(ap);");
out.println("}");
out.println();
out.println("#if !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
out.println("#if !defined(NO_JNI_DETACH_THREAD) && defined(_WIN32)");
out.println(" static __declspec(thread) struct JavaCPP_thread_local {");
out.println(" JNIEnv* env = NULL;");
out.println(" ~JavaCPP_thread_local() {");
out.println(" if (env && JavaCPP_vm) {");
out.println(" JavaCPP_vm->DetachCurrentThread();");
out.println(" }");
out.println(" }");
out.println(" } JavaCPP_thread_local; ");
out.println("#elif !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
out.println(" static pthread_key_t JavaCPP_current_env;");
out.println(" static JavaCPP_noinline void JavaCPP_detach_env(void *data) {");
out.println(" if (JavaCPP_vm) {");
Expand Down Expand Up @@ -1431,7 +1440,7 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
out.println("#endif");
out.println();
out.println("static JavaCPP_noinline void JavaCPP_detach(bool detach) {");
out.println("#if !defined(NO_JNI_DETACH_THREAD) && !defined(__linux__) && !defined(__APPLE__)");
out.println("#if !defined(NO_JNI_DETACH_THREAD) && !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)");
out.println(" if (detach && JavaCPP_vm->DetachCurrentThread() != JNI_OK) {");
out.println(" JavaCPP_log(\"Could not detach the JavaVM from the current thread.\");");
out.println(" }");
Expand Down Expand Up @@ -1462,7 +1471,12 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
out.println("#endif");
}
out.println(" }");
out.println("#if !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
out.println("#if !defined(NO_JNI_DETACH_THREAD) && defined(_WIN32)");
out.println(" if ((*env = JavaCPP_thread_local.env) != NULL) {");
out.println(" attached = true;");
out.println(" goto done;");
out.println(" }");
out.println("#elif !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
out.println(" pthread_once(&JavaCPP_once, JavaCPP_create_pthread_key);");
out.println(" if ((*env = (JNIEnv *)pthread_getspecific(JavaCPP_current_env)) != NULL) {");
out.println(" attached = true;");
Expand Down Expand Up @@ -1492,7 +1506,9 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
out.println(" *env = NULL;");
out.println(" goto done;");
out.println(" }");
out.println("#if !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
out.println("#if !defined(NO_JNI_DETACH_THREAD) && defined(_WIN32)");
out.println(" JavaCPP_thread_local.env = *env;");
out.println("#elif !defined(NO_JNI_DETACH_THREAD) && (defined(__linux__) || defined(__APPLE__))");
out.println(" pthread_setspecific(JavaCPP_current_env, *env);");
out.println("#endif");
out.println(" attached = true;");
Expand Down
9 changes: 6 additions & 3 deletions src/test/java/org/bytedeco/javacpp/ThreadTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @author Dan Avila
*
*/
@Platform(compiler = "cpp11", define = "NO_JNI_DETACH_THREAD", include = "ThreadTest.h")
@Platform(compiler = "cpp11", include = "ThreadTest.h")
public class ThreadTest {
public static class Callback extends Pointer {
/** Default native constructor. */
Expand Down Expand Up @@ -76,8 +76,8 @@ public static class Callback extends Pointer {

run(callback, count);

assertTrue(callbackValueRefs.size() == count);
assertTrue(threadRefs.size() == count);
assertEquals(callbackValueRefs.size(), count);
assertEquals(threadRefs.size(), count);

for (int i = 0; i < count; i++) {
int value = callbackValueRefs.get(i);
Expand All @@ -95,5 +95,8 @@ public static class Callback extends Pointer {

assertEquals(cbThread1, cbThread2);
}

// thread should be automatically detached upon completion
assertFalse(threadRefs.get(0).isAlive());
}
}

0 comments on commit e8aacb2

Please sign in to comment.