✆ (four oh eight) 862-7683
> Hi Enrico,
> Well, for now I can't, using the public API, lock the ScriptPythonIntepreter lock.
> I will change that class and make it use only the Python-blessed GIL locking mechanism, instead of the home-made lock. Otherwise the Python bindings will only serve for synchronous debugging, since other Python threads can never lock it.
This might be the right thing to do, or it might not.
Having multiple locking mechanisms and some code uses one and some uses another is a no-no, since that amounts to having no locking at all We need to pick one way. If the GIL approach has merits (other than being The Dogmatic Right Way), then I guess one might implement the Locker class to use Python's GIL macros.
Well, if you want to call Python code… Then you have to use the GIL. Unless you only let the user use a small python dialect (with no threading support, etc). Due to the way the Python interpreter works, You have to have the GIL locked when interpreting Python bytecode. If you want to support Python bindings, you have to choose between using the GIL or only having sync mode (without any traces of the embedded Python interpreter).
You would rewrite:
to use the GIL macros. The rest of the code should be unaffected.
Yes, that was how I was thinking about doing it. Possibly also keeping the existing ScriptInterpreter lock (at least for a while). Since it is only used when lldb interprets Python, it shouldn't even do any difference (because Python already forces every thread to lock before executing Python code). Other Python threads wouldn't stall in the middle of lldb-land because of that since every SWIG call (when the -threads argument is passed to SWIG) will unlock the GIL when leaving Python-land and lock it immediately after performing the C++ call.
However, in the future we could need to keep track of additional information for the lock. Currently, all we store is a thread-id, but being able to store additional information (e.g. which method acquired the lock) might become important. If you do a major rewrite of the locking code, you should keep this in mind as a requirement.
An alternative approach would be for your log callback function to take a struct as a baton, and have it contain the actual PyObject* wrapping the function plus a ScriptInterpreterPython*. Then you would have your SWIG-binding call routed through the ScriptInterpreter (much like it happens for data formatters today). This would enable you to merge seamlessly in the way locks are currently managed. Even better, we now have a ScriptInterpreterObject class that efficiently does the right thing when it comes to ref-counting scripted objects. If you feel the need to pass objects from Python to C++ and back, consider wrapping the PyObject*. All you need to call is ScriptInterpreterPython::MakeScriptObject and you get a C++ shared pointer to the object in return.
With the current API there is no way to access any ScriptInterpreter classes. Unless you want to expose them to the API, which can make some sense but would have to be thought through. Using this latest strategy would entail to a lot more than just changing how the lock works, since the Python API wrappers should only use the SB* API stuff.
It would also be farther from a simple bridge from Python to the C++ API and would be closer to a dedicated Python API. Would that be desired?