[C++-sig] Thread safety (original) (raw)

Patrick Hartling patrick.hartling at gmail.com
Mon Dec 19 04:15:21 CET 2005


On 12/16/05, dueymk <dueymk at everestkc.net> wrote:

Hi, I'm wrapping a multi-threaded C++ dll with Boost.Python. A thread is created when a wrapped structure is subclassed and instantiated in Python. This thread spends most of it's time in C++ but calls a virtual function which may be overridden by the Python subclass. I've done the following:

class Original { int counter; virtual bool Process(int *count) { *count++; return true; } } struct PythonOriginal : Original, wrapper { bool Process(int *count) { if (override Process = this->getoverride("Process")) { PyGILStateSTATE gstate; gstate = PyGILStateEnsure(); bool answer = call(Process.ptr(), boost::ref(count)); PyGILStateRelease(gstate); return answer; } else return Original::Process(count); } bool defaultProcess(int *count) { return this->PleoraCamera::ProcessFrame(count); } } BOOSTPYTHONMODULE(PythonOriginal) { class<PythonOriginal, boost::noncopyable >("Original") .def("Process", &Original::Process, &PythonOriginal::defaultProcess) ; } Then in Python: class PyOrig(Original): def Process(self, count): count = count + 10 return True orig = PyOrig()

The only thing I did for thread safety was to add the PyGILState calls to the virtual function wrapper around the call<>. After all that, my question is, is that sufficient? Also, are there any obvious problems with this example. It seems to work fine.

I have a very similar case with my use of Boost.Python. With my code, a Python object will be instantiated and then handed off to the multi-threaded C++ library. The Python interpreter runs in the primordial thread, but the method invocations on the Python object are made from a different thread.

My locking of the GIL has thus far been done before the call to boost::python::get_override() or any other Boost.Python functions. I changed my code so that the GIL is locked after the call to boost::python::get_override() as you have done above. I found that my code crashed at the first attempt of the C++ library's attempt to invoke a method of the Python object from a spawned thread. The crash occurred as a result of the call to boost::python::get_override() since it calls into the Python interpreter without the GIL being locked. I can provide a stack trace (from GDB) if you would like to see it.

-Patrick

-- Patrick L. Hartling http://www.137.org/patrick/



More information about the Cplusplus-sig mailing list