[C++-sig] Make threading support official

Niall Douglas s_sourceforge at nedprod.com
Thu Apr 15 15:09:46 CEST 2010


On 12 Apr 2010 at 23:20, troy d. straszheim wrote:

> I don't grok it just yet.  The code prevents locking around any call to 
> a function that returns a py_iter_, and the specialization mechanism 
> you've built would allow you to prevent locking around functions that 
> return other types, but that's all it can do.  Do you recall why you 
> needed to avoid locking here?  My guess would be that this py_iter_ 
> calls back into python, the same situation as with overrides, below.
> Are there other cases where you'd want special handling?  What if I wrap 
> a function that takes a boost::python::object (ie a call back to python 
> could happen at any time)?

I wouldn't worry about it - it is a patch designed to be reapplied to 
every new release of BPL after all, so it can never be pretty nor 
sensible. The key thing here I think is to implement formal support.

> > I have never been particularly happy with this solution because 
> > excess locking is real bad for system latency i.e. when python calls 
> > a virtual function the GIL gets unlocked, relocked, a check for a 
> > python override is made, unlocked, jump to base class implementation, 
> > on exit relock. I personally would use a technique I call "a hanging 
> > lock" whereby you wrap a parameter with a thin metaprogramming 
> > construct which lets you effectively bind a RAII held lock with a 
> > parameter such that a callee takes possession, but I don't know if 
> > this is a common technique in Boost and adding it made patching in 
> > updates too difficult.
> 
> Seems to me that if one wants to claim that boost.python "supports 
> multithreading", it needs to support this case, even if there are 
> performance hits.  I'd be interested to learn more about these hanging 
> locks...

Well hanging locks are one of the core things which made me go 
develop my own portability library rather than use an existing one. 
Boost makes a lot of use of smart pointers to implement exception 
safety. I strongly believe that Boost makes a major semantic error in 
doing this, because exception safety ought to be written in 
*explicitly* and never handled *implicitly*. Smart pointers silently 
handle exception unwinds, and while this is a good thing in the 
context of say reference counting, it is a bad thing in the case of 
std::auto_ptr<> and all its kind. auto_ptr<> is ideal for passing 
around ownership of a pointer. It is NOT the proper approach for 
cleaning up after exception throws because it doesn't force the 
programmer to explicitly code for the exception throw.

Because TnFOX doesn't make this semantic error, I can use a policy 
driven templated smart pointer where one of the policies implements 
the hanging lock. In other words, in TnFOX smart pointers don't 
"point", they *encapsulate* *metadata* with an object reference, or 
put more clearly, if you are working in TnFOX and you see a smart 
pointer being used then you can be very sure it is doing something 
special.

[FYI RAII-style exception safety in TnFOX is handled using a C++ 
concept called rollbacks where you write in the steps to undo the 
current transaction as it is being performed. If an exception happens 
anywhere during a given atomic operation, it gets undone. Because the 
programmer explicitly writes in how he implements exception safety as 
he writes his code, it makes peer code review and auditing very 
significantly easier. It is also much, much rarer that you find 
exception safety bugs, especially in algorithm implementations. If 
you want to know more, see http://tnfox.sourceforge.net/TnFOX-
svn/html/group__rollbacks.html].

Anyway, one can't just go start using hanging locks without all Boost 
programmers being used to the idea, or you'd get all sorts of bugs 
introduced. I would love some ISO C++ leadership here, especially by 
endorsing rollbacks as the preferred exception safety technique with 
a tiny bit of extra language support, but ever since they savaged me 
over rvalue references I couldn't be arsed dealing with them ever 
again.

> > I was maybe thinking of doing it properly with a boost::staticsignals 
> > library.
> 
> Ah,  I think I interpreted "static signals" to mean boost::signals (not 
> the threadsafe boost::signals2).  Anyhow, I think the user should just 
> supply something like
> 
> struct mylocker
> {
>    void enterCPP();
>    void exitCPP();
> };
> 
> boost.python would call those at the appropriate times and the user 
> could put whatever they wanted inside those functions.   I mentioned a 
> tracing facility:  maybe this interface would be more elaborate, 
> depending on where inside boost.python these calls originate...  we'll 
> see...

Looks good to me.

> > With 
> > regard to implementing support for all this, could you clarify your 
> > planned timetable with respect to your branch of Boost?
> 
> Well adding enterCPP() | exitCPP() code to my branch is easy.  It would 
> go in this file:
> 
> http://gitorious.org/~straszheim/boost/straszheims-python/blobs/master/include/boost/python/detail/caller.hpp
> 
> which has replaced all of the preprocessor stuff in detail/invoke.hpp. 
> Lines 258 and 265 are where boost::fusion actually calls the registered 
> C++ functions;  you could just (un)lock around the call to go() at line 
> 277.   Then we'd have to figure out what to do about this py_iter_ 
> stuff.  Then, AFAICT we'd have in my branch exactly what your patches do 
> to the boost.python from svn.
> 
> Note: again, that code doesn't compile with MSVC, and I don't know 
> enough about the compiler to read its mind and restructure things such 
> that it doesn't choke...   Is MSVC support a prerequisite for you to be 
> interested in all this?

MSVC support is an absolute requirement for me. Unlike others though, 
I don't care about supporting anything older than the most recently 
released free Express edition. I don't mind fixing things up to make 
it work on MSVC.

I'll tell you where I'm at timetable wise: today, after many months 
of work, I finally submit my applications for PhD funding which have 
been a pain in the hole to get done in time. Tomorrow I start work on 
a consulting contract for Applied Research Associates which I have 
had on the backburner for the past two weeks which is to implement an 
O(1) realloc() function. It will likely take me a week or two to get 
that going as it won't be easy programming. Once I have first beta 
out of that code, I would be strongly inclined to implement 
boost::staticsignals and get it working with BPL, so basically I'm 
saying I'd be able to start work on it in a couple of weeks time.

Does that suit you okay?

Cheers,
Niall




More information about the Cplusplus-sig mailing list