multithreaded PyObject_callFunction

Bryan belred1 at yahoo.com
Thu Oct 30 00:53:06 EST 2003


i've embedded python into our product and i'm not sure how to handle this situation.  the following code is a 
simplification of a function that calls a python function.  i've removed all error checking to furthur simplify the 
problem.  the following code works correctly:

void foo(context_t ctx) {
     PyObject py_interp = NULL;
     PyObject py_mod = NULL;
     PyObject py_call_foo = NULL;
     const char *mod;

     PyEval_AcquireLock();
     py_interp = get_interpreter(ctx);
     PyThreadState_Swap(py_interp);

     mod = get_module(ctx);
     py_mod = PyImport_ImportModule(mod);
     py_call_foo = PyObject_GetAttrString(py_mod, "py_foo");
     PyObject_CallFunction(py_call_foo, NULL);

     Py_XDECREF(py_interp);
     Py_XDECREF(py_mod);
     Py_XDECREF(py_call_foo);

     PyThreadState_Swap(NULL);
     PyEval_ReleaseLock();
}

now i have a situation where foo may be called at the same time in different c threads.  furthermore,  the call py_foo 
might take forever to execute and foo is then required to return immediately.  so i modified the code to something like 
this where foo starts a threaded function foo_threaded in a new thread so foo can return immediately.

void foo_threaded(void *args) {
     PyObject py_interp = NULL;
     PyObject py_mod = NULL;
     PyObject py_call_foo = NULL;
     const char *mod;

     PyEval_AcquireLock();
     py_interp = get_interpreter(ctx);
     PyThreadState_Swap(py_interp);

     mod = get_module(ctx);
     py_mod = PyImport_ImportModule(mod);
     py_call_foo = PyObject_GetAttrString(py_mod, "py_foo");
     PyObject_CallFunction(py_call_foo, NULL);

     Py_XDECREF(py_interp);
     Py_XDECREF(py_mod);
     Py_XDECREF(py_call_foo);

     PyThreadState_Swap(NULL);
     PyEval_ReleaseLock();
}


void foo(context_t ctx) {
      Thread thread;
      thread = new_thread(call_py_foo);
      thread.start()
}

this seems like the wrong approach to me.  if foo gets called a second time but the call to py_foo hasn't returned yet, 
the interpreter is still locked.  so how can another py_foo be called?  the 2nd time foo is called the call to 
get_interpreter may or may not return the same interpreter.  what am i missing?

thanks for any help.

bryan





More information about the Python-list mailing list