![]() |
|
Convenience class for accessing the Python Global Interpreter Lock. More...
#include <pyLock.h>
Public Member Functions | |
TF_API | TfPyLock () |
Acquires the Python GIL and swaps in callers thread state. | |
TF_API | ~TfPyLock () |
Releases Python GIL and restores prior threads state. | |
TF_API void | Acquire () |
(Re)acquires GIL and thread state, if previously released. | |
TF_API void | Release () |
Explicitly releases GIL and thread state. | |
TF_API void | BeginAllowThreads () |
Unlock the GIL temporarily to allow other threads to use python. | |
TF_API void | EndAllowThreads () |
End allowing other threads, reacquiring the lock state. | |
Friends | |
struct | TfPyEnsureGILUnlockedObj |
Convenience class for accessing the Python Global Interpreter Lock.
The Python API is not thread-safe. Accessing the Python API from outside the context of Python execution requires extra care when multiple threads may be present. There are various schemes for how this should be done, and the conventions have been changing with Python versions through 2.X.
This class provides a convenient and centralized location for managing the Python Global Interpreter Lock and related Python Thread State.
The easiest way to use this class is to simply create a local variable in any function that will access the Python API. Upon construction, this will acquire the Python lock and establish the correct thread state for the caller. Upon exit from the current scope, when the instance is destroyed, the thread state will be restored and the lock will be released.
If you need to temporarily release the lock during execution, (to perform blocking I/O for example), you can call Release() explicitly, then call Acquire() again to reclaim the lock.
Note that it IS EXPLICITLY OK to recursively create instances of this class, and thus recursively acquire the GIL and thread state. It is NOT OK to recursively attempt to Acquire() the same instance, that will have no effect and will generate a diagnostic warning.
This class also provides an exception-safe way to release the GIL temporarily for blocking calls, like Py_BEGIN/END_ALLOW_THREADS in the Python C API.
This looks similar to the above example using Release(), but it is different. The Python lock is recursive, so the call to Release() is not guaranteed to actually release the lock, it just releases the deepest lock. In contrast BeginAllowThreads() will fully unlock the GIL so that other threads can run temporarily regardless of how many times the lock is recursively taken.
The valid states and transitions for this class are as follows.
Released Acquire() -> Acquired Acquired Release() -> Released, BeginAllowThreads() -> AllowsThreads AllowsThreads EndAllowThreads() -> Acquired
Note that upon construction the class is in the Acquired state. Upon destruction, the class will move to the Released state.
TF_API TfPyLock | ( | ) |
Acquires the Python GIL and swaps in callers thread state.
TF_API ~TfPyLock | ( | ) |
Releases Python GIL and restores prior threads state.
TF_API void Acquire | ( | ) |
(Re)acquires GIL and thread state, if previously released.
TF_API void BeginAllowThreads | ( | ) |
Unlock the GIL temporarily to allow other threads to use python.
Typically this is used to unblock threads during operations like blocking I/O. The lock must be acquired when called.
TF_API void EndAllowThreads | ( | ) |
End allowing other threads, reacquiring the lock state.
BeginAllowThreads must have been successfully called first.
TF_API void Release | ( | ) |
Explicitly releases GIL and thread state.