mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
gh-111956: Add thread-safe one-time initialization. (gh-111960)
This commit is contained in:
parent
f66afa395a
commit
446f18a911
11 changed files with 1061 additions and 955 deletions
6
Include/internal/pycore_ast_state.h
generated
6
Include/internal/pycore_ast_state.h
generated
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#ifndef Py_INTERNAL_AST_STATE_H
|
||||
#define Py_INTERNAL_AST_STATE_H
|
||||
|
||||
#include "pycore_lock.h" // _PyOnceFlag
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -11,7 +14,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct ast_state {
|
||||
int initialized;
|
||||
_PyOnceFlag once;
|
||||
int finalized;
|
||||
int recursion_depth;
|
||||
int recursion_limit;
|
||||
PyObject *AST_type;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ typedef struct _PyMutex PyMutex;
|
|||
#define _Py_UNLOCKED 0
|
||||
#define _Py_LOCKED 1
|
||||
#define _Py_HAS_PARKED 2
|
||||
#define _Py_ONCE_INITIALIZED 4
|
||||
|
||||
// (private) slow path for locking the mutex
|
||||
PyAPI_FUNC(void) _PyMutex_LockSlow(PyMutex *m);
|
||||
|
|
@ -166,6 +167,35 @@ _PyRawMutex_Unlock(_PyRawMutex *m)
|
|||
_PyRawMutex_UnlockSlow(m);
|
||||
}
|
||||
|
||||
// A data structure that can be used to run initialization code once in a
|
||||
// thread-safe manner. The C++11 equivalent is std::call_once.
|
||||
typedef struct {
|
||||
uint8_t v;
|
||||
} _PyOnceFlag;
|
||||
|
||||
// Type signature for one-time initialization functions. The function should
|
||||
// return 0 on success and -1 on failure.
|
||||
typedef int _Py_once_fn_t(void *arg);
|
||||
|
||||
// (private) slow path for one time initialization
|
||||
PyAPI_FUNC(int)
|
||||
_PyOnceFlag_CallOnceSlow(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg);
|
||||
|
||||
// Calls `fn` once using `flag`. The `arg` is passed to the call to `fn`.
|
||||
//
|
||||
// Returns 0 on success and -1 on failure.
|
||||
//
|
||||
// If `fn` returns 0 (success), then subsequent calls immediately return 0.
|
||||
// If `fn` returns -1 (failure), then subsequent calls will retry the call.
|
||||
static inline int
|
||||
_PyOnceFlag_CallOnce(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg)
|
||||
{
|
||||
if (_Py_atomic_load_uint8(&flag->v) == _Py_ONCE_INITIALIZED) {
|
||||
return 0;
|
||||
}
|
||||
return _PyOnceFlag_CallOnceSlow(flag, fn, arg);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#ifndef Py_INTERNAL_MODSUPPORT_H
|
||||
#define Py_INTERNAL_MODSUPPORT_H
|
||||
|
||||
#include "pycore_lock.h" // _PyOnceFlag
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -65,15 +68,16 @@ PyAPI_FUNC(void) _PyArg_BadArgument(
|
|||
// --- _PyArg_Parser API ---------------------------------------------------
|
||||
|
||||
typedef struct _PyArg_Parser {
|
||||
int initialized;
|
||||
const char *format;
|
||||
const char * const *keywords;
|
||||
const char *fname;
|
||||
const char *custom_msg;
|
||||
int pos; /* number of positional-only arguments */
|
||||
int min; /* minimal number of arguments */
|
||||
int max; /* maximal number of positional arguments */
|
||||
PyObject *kwtuple; /* tuple of keyword parameter names */
|
||||
_PyOnceFlag once; /* atomic one-time initialization flag */
|
||||
int is_kwtuple_owned; /* does this parser own the kwtuple object? */
|
||||
int pos; /* number of positional-only arguments */
|
||||
int min; /* minimal number of arguments */
|
||||
int max; /* maximal number of positional arguments */
|
||||
PyObject *kwtuple; /* tuple of keyword parameter names */
|
||||
struct _PyArg_Parser *next;
|
||||
} _PyArg_Parser;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ extern "C" {
|
|||
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_state
|
||||
|
||||
struct _getargs_runtime_state {
|
||||
PyThread_type_lock mutex;
|
||||
struct _PyArg_Parser *static_parsers;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue