[C++-sig] Re: boost::python and threads

Vladimir Vukicevic vladimir at pobox.com
Mon Jul 14 02:18:03 CEST 2003


On Sun, 2003-07-13 at 14:40, David Abrahams wrote:
> Vladimir Vukicevic <vladimir at pobox.com> writes:
> 
> > Sorry 'bout that, I was in a hurry when I wrote that and didn't manage
> > to explain concisely.
> >
> > Essentially what I think needs to happen is the following:
> >
> > 1. The GIL needs to be acquired at every point that python calls into
> > boost::python glue code.  
> 
> I don't think so!
> 
> When Python calls boost::python it *always* has the GIL already.  It
> looks like you have way too many detail::gil_lock instances in your
> patch.  GUI acquisition needs to be done when C++ code calls back into
> python.

Hmm.. you're right.  There were a few problems that I had going on that
made me put in a lot of gil_lock's, more so than what are needed.  I'll
have to go through and examine again exactly where they need to go.

> > (Any such acquisition should be optional, such that extensions that
> > don't care about threads don't have to deal with the overhead.)
> 
> Which is why I don't understand the need for call_with_gil<>.  What's
> wrong with asking the user to create a local gil_lock of his own?  He
> might need one anyway, since he may need to use the
> Boost.Python/Python API himself.

Sure, sounds good.

> > 2. The GIL needs to be released (threads "allowed") around every call to
> > a native C++ function wrapped by boost::python.  (This function should,
> > if it needs to call Python or boost::python API calls, acquire the GIL
> > itself.)
> 
> No way.  That incurs way too much overhead for small wrapped
> functions.  Releasing the GIL when we call a wrapped C++ function
> needs to be optional (possibly globally settable).

Are you thinking settable at runtime or at compile time?  If at compile
time, then defining BOOST_PYTHON_NO_THREADING causes
gil_lock/thread_block to just be dummy stubs.  I don't see how you'd do
it for some methods and not for others, without adding extra logic to
the path that leads to invoke() -- which I guess may be the right thing
to do for a fully general solution.

> In any case, even if it's not optional you have a problem because
> you're releasing the GIL when calling into functions that accept,
> e.g. python::object parameters.  You haven't patched
> object::object(object const&) to acquire the gil.  You'd need to find
> *every* PyXXXX in the library and make sure the GIL is acquired.  All
> that aqcuiring/releasing could get expensive, and I'm not comfortable
> with that.

Yup, there's still a bunch of places where the locks aren't correct. 
Expensive or not though, I don't see a way around it -- you're either
not thread safe (in which case you go the BOOST_PYTHON_NO_THREADING
route at compile time), or you are -- eventually one could probably
build separate boost_python .so with and without thread safety so that
extensions can choose which version to link/build with.

Thanks for the feedback,
	- Vlad






More information about the Cplusplus-sig mailing list