Hello,
Multi-threading is not an easy thing to master. Synchronisation problems are particularly painful to debug and not always reproducible.
That said, using the macros you have mentioned, one can unlock the Python GIL alright.
If your code is pure C/C++ and does not, in any way, call back the Python API, you're good.
If your code depends on the Python API or objects generated in Python, then care must the taken to ensure that none of the objects being used by your unlocked code will vanish because the interpreter just decided. One common way is by re-acquiring the GIL for those interactions with Python objects.
Some consequences from my mind:
1. Logging at Bob is diverged to python logging. If I remember correctly, I re-acquire the lock before emitting any message, but one must observe that, if the code calls the logging module too often and logging is diverged to Python logging, then in practice this will hit your potential speed-up to the point MT becomes useless.
2. Our blitz-numpy bridge sometimes produces blitz::Arrays which point to numpy array memory. For efficiency reasons, we avoid data copying when we can. If the array ceases to exist while the thread is running, this may lead to unpredictable crashes.
3. You may not call any Py* or PyArray* or PyBlitzArray* while you're at the C++ code. These all require the GIL to be active.
There you are, my 2 cents on this subject!
A