Updated version with new names and no (known!) outstanding issues.

This commit is contained in:
Mark Hammond 2003-04-19 01:11:23 +00:00
parent 22e655ac93
commit ef84c41022
1 changed files with 42 additions and 64 deletions

View File

@ -7,27 +7,7 @@ Status: Draft
Type: Standards Track
Content-Type: text/plain
Created: 05-Feb-2003
Post-History: 05-Feb-2003 14-Feb-2003
Open Issues
This is where I note comments from people that are yet to be
resolved.
- JustvR prefers a PyGIL prefix over PyAutoThreadState.
- JackJ notes that the "Auto" prefix will look a little silly
in a few years, assuming this becomes the standard way of
managing the lock. He doesn't really like Just's "GIL", and
suggested "PyIntLock"
- JackJ prefers "Acquire" over "Ensure", even though the semantics
are different than for other "Acquire" functions in the API.
Mark still prefers Ensure for exactly this reason.
- Mark notes Dutch people must love names, and still remembers
"pulling dead cows from the ditch" (but has forgotten the
Dutch!) He also hopes Jack remembers the reference <wink>.
- Should we provide Py_AUTO_THREAD_STATE macros?
- Is my "Limitation" regarding PyEval_InitThreads() OK?
Post-History: 05-Feb-2003 14-Feb-2003 19-Apr-2003
Abstract
@ -139,67 +119,65 @@ Proposal
the management of the GIL. This API will be available on all
platforms built with WITH_THREAD defined.
The intent is that an extension author be able to use a small,
well-defined "prologue dance", at any time and on any thread, and
assuming Python has correctly been initialized, this dance will
ensure Python is ready to be used on that thread. After the
extension has finished with Python, it must also perform an
"epilogue dance" to release any resources previously acquired.
Ideally, these dances can be expressed in a single line.
The intent is that assuming Python has correctly been initialized,
an extension author be able to use a small, well-defined "prologue
dance", at any time and on any thread, which will ensure Python
is ready to be used on that thread. After the extension has
finished with Python, it must also perform an "epilogue dance" to
release any resources previously acquired. Ideally, these dances
can be expressed in a single line.
Specifically, the following new APIs are proposed:
/* Ensure that the current thread is ready to call the Python C
API, regardless of the current state of Python, or of its thread
lock. This may be called as many times as desired by a thread, so
long as each call is matched with a call to
PyAutoThreadState_Release()
The return value is an opaque "handle" to the thread state when
PyAutoThreadState_Ensure() was called, and must be passed to
PyAutoThreadState_Release() to ensure Python is left in the same
state.
When the function returns, the current thread will hold the GIL.
Thus, the GIL is held by the thread until
PyAutoThreadState_Release() is called. (Note that as happens now
in Python, calling a Python API function may indeed cause a
thread-switch and therefore a GIL ownership change. However,
Python guarantees that when the API function returns, the GIL will
again be owned by the thread making the call)
Failure is a fatal error.
/* Ensure that the current thread is ready to call the Python
C API, regardless of the current state of Python, or of its
thread lock. This may be called as many times as desired
by a thread so long as each call is matched with a call to
PyGILState_Release(). In general, other thread-state APIs may
be used between _Ensure() and _Release() calls, so long as the
thread-state is restored to its previous state before the Release().
For example, normal use of the Py_BEGIN_ALLOW_THREADS/
Py_END_ALLOW_THREADS macros are acceptable.
The return value is an opaque "handle" to the thread state when
PyGILState_Acquire() was called, and must be passed to
PyGILState_Release() to ensure Python is left in the same state. Even
though recursive calls are allowed, these handles can *not* be
shared - each unique call to PyGILState_Ensure must save the handle
for its call to PyGILState_Release.
When the function returns, the current thread will hold the GIL.
Failure is a fatal error.
*/
PyAutoThreadState_State PyAutoThreadState_Ensure(void);
PyAPI_FUNC(PyGILState_STATE) PyGILState_Ensure(void);
/* Release any resources previously acquired. After this call,
Python's state will be the same as it was prior to the
corresponding PyAutoThreadState_Ensure call (but generally this
state will be unknown to the caller, hence the use of the
AutoThreadState API.)
Every call to PyAutoThreadState_Ensure must be matched by a
call to PyAutoThreadState_Release on the same thread.
/* Release any resources previously acquired. After this call, Python's
state will be the same as it was prior to the corresponding
PyGILState_Acquire call (but generally this state will be unknown to
the caller, hence the use of the GILState API.)
Every call to PyGILState_Ensure must be matched by a call to
PyGILState_Release on the same thread.
*/
void PyAutoThreadState_Release(PyAutoThreadState_State state);
PyAPI_FUNC(void) PyGILState_Release(PyGILState_STATE);
Common usage will be:
void SomeCFunction(void)
{
/* ensure we hold the lock */
PyAutoThreadState_State state = PyAutoThreadState_Ensure();
PyGILState_STATE state = PyGILState_Ensure();
/* Use the Python API */
...
/* Restore the state of Python */
PyAutoThreadState_Release(state);
PyGILState_Release(state);
}
Design and Implementation
The general operation of PyAutoThreadState_Ensure() will be:
The general operation of PyGILState_Ensure() will be:
- assert Python is initialized.
- Get a PyThreadState for the current thread, creating and saving
if necessary.
@ -212,10 +190,10 @@ Design and Implementation
The general operation of PyAutoThreadState_Release() will be:
- assert our thread currently holds the lock.
- If old state indicates lock as previously unlocked, release GIL.
- If old state indicates lock was previously unlocked, release GIL.
- Decrement the PyAutoThreadState_Ensure counter for the thread.
- If counter == 0:
- release the PyThreadState.
- release and delete the PyThreadState.
- forget the ThreadState as being owned by the thread.
- return