-
Notifications
You must be signed in to change notification settings - Fork 588
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Switch to
AttachCurrentThreadAsDaemon()
when attaching native th…
…reads on callback (pull #561)
- Loading branch information
1 parent
6480444
commit 9a57b0d
Showing
5 changed files
with
123 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
.classpath | ||
.project | ||
.settings | ||
.factorypath | ||
|
||
# IntelliJ | ||
*.iml | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package org.bytedeco.javacpp; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
import java.io.File; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
|
||
import org.bytedeco.javacpp.annotation.Platform; | ||
import org.bytedeco.javacpp.annotation.Virtual; | ||
import org.bytedeco.javacpp.tools.Builder; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
|
||
/** | ||
* This test case verifies that threads attached from the native layer are | ||
* configured as daemons and can remain attached when the appropriate property | ||
* is specified. | ||
* <p> | ||
* You would want this behavior when you have a callback that is called with a | ||
* high frequency. | ||
* | ||
* @author Dan Avila | ||
* | ||
*/ | ||
@Platform(compiler = "cpp11", define = "NO_JNI_DETACH_THREAD", include = "ThreadTest.h") | ||
public class ThreadTest { | ||
public static class Callback extends Pointer { | ||
/** Default native constructor. */ | ||
public Callback() { super((Pointer) null); allocate(); } | ||
/** Native array allocator. Access with {@link Pointer#position(long)}. */ | ||
public Callback(long size){ super((Pointer) null); allocateArray(size); } | ||
/** Pointer cast constructor. Invokes {@link Pointer#Pointer(Pointer)}. */ | ||
public Callback(Pointer p) { super(p); } | ||
|
||
private native void allocate(); | ||
private native void allocateArray(long size); | ||
|
||
@Override public Callback position(long position) { | ||
return (Callback)super.position(position); | ||
} | ||
|
||
@Override public Callback getPointer(long i) { | ||
return new Callback((Pointer)this).offsetAddress(i); | ||
} | ||
|
||
@Virtual(true) public native void callback(int value); | ||
} | ||
|
||
static native void run(Callback callback, int count); | ||
|
||
@BeforeClass public static void setUpClass() throws Exception { | ||
System.out.println("Builder"); | ||
Class c = ThreadTest.class; | ||
Builder builder = new Builder().classesOrPackages(c.getName()); | ||
File[] outputFiles = builder.build(); | ||
|
||
System.out.println("Loader"); | ||
Loader.load(c); | ||
} | ||
|
||
@Test public void testJNIThreadAttachFromNativeCallbacks() { | ||
final int count = 10; | ||
final List<Integer> callbackValueRefs = new ArrayList<>(); | ||
final List<Thread> threadRefs = new ArrayList<>(); | ||
|
||
Callback callback = new Callback() { | ||
@Override public void callback(int value) { | ||
System.out.println("Callback from " + Thread.currentThread()); | ||
callbackValueRefs.add(Integer.valueOf(value)); | ||
threadRefs.add(Thread.currentThread()); | ||
} | ||
}; | ||
|
||
run(callback, count); | ||
|
||
assertTrue(callbackValueRefs.size() == count); | ||
assertTrue(threadRefs.size() == count); | ||
|
||
for (int i = 0; i < count; i++) { | ||
int value = callbackValueRefs.get(i); | ||
Thread callbackThread = threadRefs.get(i); | ||
|
||
assertEquals("Callback was not called", i + 1, value); | ||
|
||
assertNotEquals("Callback thread is not main", Thread.currentThread(), callbackThread); | ||
assertTrue("Callback thread is daemon", callbackThread.isDaemon()); | ||
} | ||
|
||
for (int i = 1; i < count; i++) { | ||
Thread cbThread1 = threadRefs.get(i - 1); | ||
Thread cbThread2 = threadRefs.get(i); | ||
|
||
assertEquals(cbThread1, cbThread2); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#include <thread> | ||
|
||
class Callback { | ||
public: | ||
virtual void callback(int value) = 0; | ||
}; | ||
|
||
static void doIt(Callback* callback, int value) { | ||
for(int i = 1; i <= value; i++) { | ||
callback->callback(i); | ||
} | ||
} | ||
|
||
static void run(Callback* callback, int count) { | ||
std::thread thread(doIt, callback, count); | ||
|
||
thread.join(); | ||
} |