changeset 3305:7397f29e133a octave-forge

Add thread-safe java->octave callback mechanism.
author goffioul
date Wed, 04 Apr 2007 12:38:30 +0000
parents 3db99bf6f6ee
children 4a1cee2f90d3
files extra/java/src/__java__.cc extra/java/src/org/octave/Octave.java extra/java/src/org/octave/OctaveReference.java
diffstat 3 files changed, 99 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/extra/java/src/__java__.cc	Wed Apr 04 05:51:07 2007 +0000
+++ b/extra/java/src/__java__.cc	Wed Apr 04 12:38:30 2007 +0000
@@ -33,12 +33,18 @@
 
 extern "C" JNIEXPORT jboolean JNICALL Java_org_octave_Octave_call
   (JNIEnv *, jclass, jstring, jobjectArray, jobjectArray);
+  /*
 extern "C" JNIEXPORT void JNICALL Java_org_octave_OctListener_doInvokeListener
   (JNIEnv *, jclass, jint, jstring, jobject);
+  */
 extern "C" JNIEXPORT void JNICALL Java_org_octave_OctaveReference_doFinalize
   (JNIEnv *, jclass, jint);
-extern "C" JNIEXPORT jobject JNICALL Java_org_octave_OctaveReference_doInvoke
+extern "C" JNIEXPORT void JNICALL Java_org_octave_Octave_doInvoke
   (JNIEnv *, jclass, jint, jobjectArray);
+extern "C" JNIEXPORT void JNICALL Java_org_octave_Octave_doEvalString
+  (JNIEnv *, jclass, jstring);
+extern "C" JNIEXPORT jboolean JNICALL Java_org_octave_Octave_needThreadedInvokation
+  (JNIEnv *, jclass);
 
 static JavaVM *jvm = 0;
 static JNIEnv *jni_env = 0;
@@ -47,6 +53,7 @@
 static std::map<int,octave_value> listener_map;
 static std::map<int,octave_value> octave_ref_map;
 static int octave_refcount = 0;
+static int octave_thread_ID = -1;
 
 template <class T>
 class java_local_ref
@@ -1149,8 +1156,8 @@
 {
   if (jni_env)
     {
-      jclass_ref cls = jni_env->FindClass ("org/octave/OctListener");
-      jmethodID mID = jni_env->GetStaticMethodID (cls, "checkPendingListener", "()V");
+      jclass_ref cls = jni_env->FindClass ("org/octave/Octave");
+      jmethodID mID = jni_env->GetStaticMethodID (cls, "checkPendingAction", "()V");
       jni_env->CallStaticVoidMethod (cls, mID);
     }
   return 0;
@@ -1165,6 +1172,9 @@
         {
           octave_java::register_type ();
           command_editor::set_event_hook (java_event_hook);
+#ifdef __WIN32__
+          octave_thread_ID = GetCurrentThreadId();
+#endif
         }
       else
         error (msg.c_str ());
@@ -1438,6 +1448,7 @@
   return false;
 }
 
+/*
 JNIEXPORT void JNICALL Java_org_octave_OctListener_doInvokeListener
   (JNIEnv *env, jclass, jint ID, jstring name, jobject event)
 {
@@ -1461,6 +1472,7 @@
   else
     printf ("invalid listener ID=%d\n", ID);
 }
+*/
 
 JNIEXPORT void JNICALL Java_org_octave_OctaveReference_doFinalize
   (JNIEnv *env, jclass, jint ID)
@@ -1468,7 +1480,7 @@
   octave_ref_map.erase (ID);
 }
 
-JNIEXPORT jobject JNICALL Java_org_octave_OctaveReference_doInvoke
+JNIEXPORT void JNICALL Java_org_octave_Octave_doInvoke
   (JNIEnv *env, jclass, jint ID, jobjectArray args)
 {
   std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
@@ -1492,10 +1504,26 @@
           if (val.is_function_handle ())
             {
               octave_function *fcn = val.function_value ();
-	      feval (fcn, oct_args);
+              feval (fcn, oct_args);
             }
         }
     }
+}
 
-  return 0;
+JNIEXPORT void JNICALL Java_org_octave_Octave_doEvalString
+  (JNIEnv *env, jclass, jstring cmd)
+{
+  std::string s = jstring_to_string (cmd);
+  int pstatus;
+
+  eval_string (s, false, pstatus, 0);
 }
+
+JNIEXPORT jboolean JNICALL Java_org_octave_Octave_needThreadedInvokation
+  (JNIEnv *env, jclass)
+{
+#ifdef __WIN32__
+  return (GetCurrentThreadId() != octave_thread_ID);
+#endif
+  return false;
+}
--- a/extra/java/src/org/octave/Octave.java	Wed Apr 04 05:51:07 2007 +0000
+++ b/extra/java/src/org/octave/Octave.java	Wed Apr 04 12:38:30 2007 +0000
@@ -7,7 +7,62 @@
     System.load (System.getProperty ("octave.java.path") + java.io.File.separator + "__java__.oct");
   }
 
+  private static Object notifyObject = null;
+  private static Object[] args = null;
+
   public native static boolean call (String name, Object[] argin, Object[] argout);
+  public native static void doInvoke(int ID, Object[] args);
+  public native static void doEvalString(String cmd);
+  public native static boolean needThreadedInvokation();
+
+  public static void checkPendingAction()
+    {
+      if (notifyObject != null)
+        {
+          synchronized(notifyObject)
+            {
+              if (notifyObject instanceof OctaveReference)
+                doInvoke(((OctaveReference)notifyObject).getID(), args);
+              else if (notifyObject instanceof String)
+                doEvalString((String)notifyObject);
+              notifyObject.notifyAll();
+            }
+          notifyObject = null;
+          args = null;
+        }
+    }
+
+  public static void invokeAndWait(OctaveReference ref, Object[] invokeArgs)
+    {
+      if (needThreadedInvokation())
+        {
+          synchronized(ref)
+            {
+              notifyObject = ref;
+              args = invokeArgs;
+              try { ref.wait(); }
+              catch (InterruptedException e) {}
+            }
+        }
+      else
+        doInvoke(ref.getID(), invokeArgs);
+    }
+
+  public static void evalAndWait(String cmd)
+    {
+      if (needThreadedInvokation())
+        {
+          synchronized(cmd)
+            {
+              notifyObject = cmd;
+              args = null;
+              try { cmd.wait(); }
+              catch (InterruptedException e) {}
+            }
+        }
+      else
+        doEvalString(cmd);
+    }
 
   public static Object do_test (String name, Object arg0) throws Exception
     {
--- a/extra/java/src/org/octave/OctaveReference.java	Wed Apr 04 05:51:07 2007 +0000
+++ b/extra/java/src/org/octave/OctaveReference.java	Wed Apr 04 12:38:30 2007 +0000
@@ -15,7 +15,6 @@
 	}
 
 	private native static void doFinalize(int ID);
-	private native static Object doInvoke(int ID, Object[] args);
 
 	protected void finalize() throws Throwable
 	{
@@ -34,6 +33,15 @@
 
 	public Object invoke(Object[] args)
 	{
-		return doInvoke(this.ID, args);
+		//System.out.println("OctaveReference::invoke");
+		Octave.doInvoke(this.ID, args);
+		return null;
+	}
+
+	public synchronized Object invokeAndWait(Object[] args)
+	{
+		//System.out.println("OctaveReference::invokeandWait");
+		Octave.invokeAndWait(this, args);
+		return null;
 	}
 }