mirror of
https://github.com/netbirdio/gomobile-tvos-fork.git
synced 2026-05-22 18:43:29 -07:00
mobile/bind: ensure that Java->Go->Java calls stay on same thread
Java methods from Go are run on a thread pool managed on the Java side, to avoid the complexities of getting Go threads to play along with the Android JVM. However, for call stacks that contain a Java->Go->Java chain, this behaviour confuses Java code sensitive to specific threads if the Go->Java call is executed on an arbitrary thread from the pool. For example, most Android UI changes must happen on the single UI thread. Replace the thread pool with direct calls to mimic ObjC<->Go and Java->Go calls. Threads not already attached to the JVM are attached. Introduce a thread local variable to detach such threads at thread exit. Change-Id: I8cb65803c9278666ae77a0c7a65dc2d9c7e739e1 Reviewed-on: https://go-review.googlesource.com/19334 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
committed by
Hyang-Ah Hana Kim
parent
7538792349
commit
46f9e01d1e
+10
-47
@@ -5,8 +5,6 @@
|
||||
package go;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
// Seq is a sequence of machine-dependent encoded values.
|
||||
@@ -30,9 +28,6 @@ public class Seq {
|
||||
}
|
||||
|
||||
initSeq();
|
||||
new Thread("GoSeq") {
|
||||
public void run() { Seq.receive(); }
|
||||
}.start();
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@@ -108,55 +103,23 @@ public class Seq {
|
||||
// a Ref to the receiver.
|
||||
public static native void send(String descriptor, int code, Seq src, Seq dst);
|
||||
|
||||
// recv returns the next request from Go for a Java call.
|
||||
static native void recv(Seq in, Receive params);
|
||||
|
||||
// recvRes sends the result of a Java call back to Go.
|
||||
static native void recvRes(int handle, Seq out);
|
||||
|
||||
static final class Receive {
|
||||
int refnum;
|
||||
int code;
|
||||
int handle;
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
free();
|
||||
}
|
||||
private native void free();
|
||||
|
||||
private static final ExecutorService receivePool = Executors.newCachedThreadPool();
|
||||
|
||||
// receive listens for callback requests from Go, invokes them on a thread
|
||||
// pool and sends the responses.
|
||||
public static void receive() {
|
||||
Seq.Receive params = new Seq.Receive();
|
||||
while (true) {
|
||||
final Seq in = new Seq();
|
||||
Seq.recv(in, params);
|
||||
|
||||
final int code = params.code;
|
||||
final int handle = params.handle;
|
||||
final int refnum = params.refnum;
|
||||
|
||||
if (code == -1) {
|
||||
// Special signal from seq.FinalizeRef.
|
||||
tracker.dec(refnum);
|
||||
Seq out = new Seq();
|
||||
Seq.recvRes(handle, out);
|
||||
continue;
|
||||
}
|
||||
|
||||
receivePool.execute(new Runnable() {
|
||||
public void run() {
|
||||
Ref r = tracker.get(refnum);
|
||||
Seq out = new Seq();
|
||||
r.obj.call(code, in, out);
|
||||
Seq.recvRes(handle, out);
|
||||
}
|
||||
});
|
||||
public static Seq recv(Seq in, int code, int refnum) {
|
||||
Seq out = new Seq();
|
||||
if (code == -1) {
|
||||
// Special signal from seq.FinalizeRef.
|
||||
tracker.dec(refnum);
|
||||
return out;
|
||||
}
|
||||
|
||||
Ref r = tracker.get(refnum);
|
||||
r.obj.call(code, in, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// An Object is a Java object that matches a Go object.
|
||||
|
||||
Reference in New Issue
Block a user