Re: [pygccxml-development] Feature request: Creating thread safe methods
Brought to you by:
mbaas,
roman_yakovenko
From: Matthias B. <ba...@ir...> - 2006-07-31 14:20:57
|
Roman Yakovenko wrote: > May be we should add to boost::python library simple guard: > struct gilguard{ > gilguard(){ PyGILState_Ensure() ; } > ~gilguard(){ PyGILState_Release(); } > }; > > Thus the generated code will be able to use the guard and it will be > exception neutral. This is a good idea for the case when the entire function/method has to be surrounded by the above calls. But in the case of our wrapper methods it would be more efficient to do the original function call outside the locking to prevent other threads from being blocked. Currently the wrapper code for virtual member functions looks somewhat like this: virtual void foo(){ if( bp::override func_foo = this->get_override( "foo" ) ) func_foo( ); else Foo::foo( ); } Surrounding the entire function body with the Ensure() and Release() calls would work but I think it's too conservative. In the case when the original Foo:foo() function is invoked the interpreter lock is not necessary anymore and it would just prevent other threads from being able to execute Python code. So I think the wrapper code should rather look like this: virtual void foo(){ PyGILState_STATE gstate; gstate = PyGILState_Ensure(); bp::override func_foo = this->get_override( "foo" ); if( func_foo ) { func_foo( ); // at this point the user might want to add code that // checks for exceptions (or does the above function // call already raise a C++ exception? then there // should be a try...catch block) } PyGILState_Release(gstate); if (!func_foo) Foo::foo( ); } >> However, this code is generated by pyplusplus and currently I don't see >> a way to inject the extra code. > > Now can you see the problem with virtual functions and arguments policies? > They don't work well together :-(. The main problem is that function > signature is changed. Well, yes, but in this case we are actually dealing with two wrapper methods, aren't we? One for the case when the call is made from C++ and one for the case when the call is made from Python. So far, my existing arg policies are dealing with the case when the call is made from Python and goes down to C++. Hm, maybe the other direction just needs a separate set of "arg policy" classes....? So far, the virtual methods in the Maya SDK are always called from C++, so I would only need one direction. But I have only considered a few classes and methods yet, there might still be methods where the derived class wants to invoke the inherited method... >> Maybe this flag could even have three states so >> that in addition to True and False there's the option to use a global >> default value. This means the user could simply set the default value to >> specify if he wants to create thread-safe bindings or not. > > mb.calldefs().thread_safe = True Well, ok. I just thought it would be more efficient and spare one query, but the above is fine with me. >> Another question is if pyplusplus should ever add the locking functions >> to non-virtual methods. In principle, non-virtual methods are always >> thread-safe unless the method invokes Python code internally (which is >> probably a really rare case). > > I don't know. Also I prefer to develop py++ having real use cases. > So the answer is next: if you don't have such use case we will not > write the code that will treat it. ok. As I already said, I think it's really a rare case where someone would need this. Usually, the methods will be virtual so that you can override the methods and implement them in Python. >> Then there's another issue related to thread-safety. Locking the Python >> interpreter is one thing, but you also have to catch any exception that >> is raised in the Python code and take some appropriate actions (like >> reporting the exception and, in my case, returning an appropriate error >> status code to Maya). > > Will exception neutral code will solve this problem? What do you mean by this? > If not, I think py++ > should have functionality, that will allow user to add/modify/rewrite > code generated > by py++. If this functionality will be added, we could implement > "arguments policy" > functionality out side of py++. If you mean that the actual policy class is outside py++ (but of course, the framework for this to work is inside py++), then I agree.... :) > Every overridable virtual member function looks like: > > 0 virtual int pure_virtual( int x ){ > 1 > 2 bp::override func_pure_virtual = this->get_override( "pure_virtual" ); > 3 > 4 return func_pure_virtual( x ); > 5 > 6 } > > It seems, that user needs to add code to 1, 3, 5 and to be able to > modify 2,4. Am I right? In principle, yes. Of course, as I wasn't dealing with virtual methods yet I have no distinction between 1 and 3 (as line 2 doesn't appear in the code generated by the existing arg policy mechanism), so both of them would be "pre-call" whereas 5 is "post-call". Additionally, there should be a way to allocate local variables (this has to be done via an API call so that the variable name can be adjusted if necessary to prevent name clashes). - Matthias - |