I would like to propose the attached patch to support the use of python sub-interpreters, which are used by mod_wsgi. If there is interest, I can further clarify.

Pat

Index: jcc/jcc/sources/JCCEnv.h
===================================================================
--- jcc/jcc/sources/JCCEnv.h	(revision 1358032)
+++ jcc/jcc/sources/JCCEnv.h	(working copy)
@@ -56,9 +56,11 @@
 #ifdef _jcc_shared
 _DLL_IMPORT extern JCCEnv *env;
 _DLL_IMPORT extern DWORD VM_ENV;
+_DLL_IMPORT extern DWORD PY_THREAD_STATE;
 #else
 _DLL_EXPORT extern JCCEnv *env;
 _DLL_EXPORT extern DWORD VM_ENV;
+_DLL_EXPORT extern DWORD PY_THREAD_STATE;
 #endif
 
 #else
@@ -123,18 +125,28 @@
 #if defined(_MSC_VER) || defined(__WIN32)
     inline JNIEnv *get_vm_env() const
     {
-        return (JNIEnv *) TlsGetValue(VM_ENV);
+        return (JNIEnv *) (VM_ENV ? TlsGetValue(VM_ENV) : NULL);
     }
+    inline PyThreadState *get_py_thread_state() const
+    {
+        return (PyThreadState *) (PY_THREAD_STATE ? TlsGetValue(PY_THREAD_STATE) : NULL);
+    }
 #else
     static pthread_key_t VM_ENV;
+    static pthread_key_t PY_THREAD_STATE;
 
     inline JNIEnv *get_vm_env() const
     {
-        return (JNIEnv *) pthread_getspecific(VM_ENV);
+        return (JNIEnv *) (VM_ENV ? pthread_getspecific(VM_ENV) : NULL);
     }
+    inline PyThreadState *get_py_thread_state() const
+    {
+        return (PyThreadState *) (PY_THREAD_STATE ? pthread_getspecific(PY_THREAD_STATE) : NULL);
+    }
 #endif
     void set_vm(JavaVM *vm, JNIEnv *vm_env);
     void set_vm_env(JNIEnv *vm_env);
+    void set_py_thread_state(PyThreadState *);
     int attachCurrentThread(char *name, int asDaemon);
 
     jint getJNIVersion() const;
@@ -300,37 +312,55 @@
 
 class PythonGIL {
   private:
+    bool initial;
     PyGILState_STATE state;
   public:
     PythonGIL()
     {
-        state = PyGILState_Ensure();
+        lock();
     }
     PythonGIL(JNIEnv *vm_env)
     {
-        state = PyGILState_Ensure();
+        lock();
         env->set_vm_env(vm_env);
     }
     ~PythonGIL()
     {
-        PyGILState_Release(state);
+        if (initial)
+            PyGILState_Release(state);
+        else
+            env->set_py_thread_state(PyEval_SaveThread());
     }
+  private:
+    void lock()
+    {
+        PyThreadState *thread_state = env->get_py_thread_state();
+        if (!thread_state)
+	{
+            state = PyGILState_Ensure();
+            initial = true;
+        }
+        else
+	{
+            PyEval_RestoreThread(thread_state);
+            initial = false;
+        }
+    }
 };
 
 class PythonThreadState {
   private:
-    PyThreadState *state;
     int handler;
   public:
     PythonThreadState(int handler=0)
     {
-        state = PyEval_SaveThread();
+        env->set_py_thread_state(PyEval_SaveThread());
         this->handler = handler;
         env->handlers += handler;
     }
     ~PythonThreadState()
     {
-        PyEval_RestoreThread(state);
+        PyEval_RestoreThread(env->get_py_thread_state());
         env->handlers -= handler;
     }
 };
Index: jcc/jcc/sources/JCCEnv.cpp
===================================================================
--- jcc/jcc/sources/JCCEnv.cpp	(revision 1358032)
+++ jcc/jcc/sources/JCCEnv.cpp	(working copy)
@@ -20,8 +20,10 @@
 
 #if defined(_MSC_VER) || defined(__WIN32)
 _DLL_EXPORT DWORD VM_ENV = 0;
+_DLL_EXPORT DWORD PY_THREAD_STATE = 0;
 #else
 pthread_key_t JCCEnv::VM_ENV = (pthread_key_t) NULL;
+pthread_key_t JCCEnv::PY_THREAD_STATE = (pthread_key_t) NULL;
 #endif
 
 #if defined(_MSC_VER) || defined(__WIN32)
@@ -204,20 +206,46 @@
 
 void JCCEnv::set_vm_env(JNIEnv *vm_env)
 {
-    if (!VM_ENV)
-        VM_ENV = TlsAlloc();
+    if (!VM_ENV) {
+        lock locked;
+        if (!VM_ENV)
+            VM_ENV = TlsAlloc();
+    }
     TlsSetValue(VM_ENV, (LPVOID) vm_env);
 }
 
+void JCCEnv::set_py_thread_state(PyThreadState *py_thread_state)
+{
+    if (!PY_THREAD_STATE) {
+        lock locked;
+        if (!PY_THREAD_STATE)
+            PY_THREAD_STATE = TlsAlloc();
+    }
+    TlsSetValue(PY_THREAD_STATE, (LPVOID) py_thread_state);
+}
+
 #else
 
 void JCCEnv::set_vm_env(JNIEnv *vm_env)
 {
-    if (!VM_ENV)
-        pthread_key_create(&VM_ENV, NULL);
+    if (!VM_ENV) {
+        lock locked;
+        if (!VM_ENV)
+            pthread_key_create(&VM_ENV, NULL);
+    }
     pthread_setspecific(VM_ENV, (void *) vm_env);
 }
 
+void JCCEnv::set_py_thread_state(PyThreadState *py_thread_state)
+{
+    if (!PY_THREAD_STATE) {
+        lock locked;
+        if (!PY_THREAD_STATE)
+            pthread_key_create(&PY_THREAD_STATE, NULL);
+    }
+    pthread_setspecific(PY_THREAD_STATE, (void *) py_thread_state);
+}
+
 #endif
 
 jint JCCEnv::getJNIVersion() const

Reply via email to