-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Closed
Labels
3.13bugs and security fixesbugs and security fixestopic-free-threadingtype-featureA feature request or enhancementA feature request or enhancement
Description
Feature or enhancement
Some CPython internals require initialization exactly once. Some of these one time initializations are not thread-safe without the GIL or have data races according to the C11 memory model.
We should add a lightweight, thread-safe one-time initialization API similar to C++11's std::call_once
1. The proposed internal-only API follows C++11's std::call_once
, but adapted for C (i.e., error returns and function pointers):
typedef struct {
uint8_t v;
} _PyOnceFlag;
typedef int _Py_once_fn_t(void *arg);
// Calls `fn` once using `flag`. The `arg` is passed to the call to `fn`.
//
// Returns 1 on success and 0 on failure.
//
// If `fn` returns 1 (success), then subsequent calls immediately return 1.
// If `fn` returns 0 (failure), then subsequent calls will retry the call.
int _PyOnceFlag_CallOnce(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg);
As an example, the Python-ast.c
relies on the GIL and an initialized
variable to ensure that it is only initialized once:
Lines 1126 to 1135 in d61313b
static int | |
init_types(struct ast_state *state) | |
{ | |
// init_types() must not be called after _PyAST_Fini() | |
// has been called | |
assert(state->initialized >= 0); | |
if (state->initialized) { | |
return 1; | |
} |
Linked PRs
Footnotes
-
Also,
pthread_once
and C11'scall_once
.std::call_once
supports error returns, which is important for CPython's use cases. ↩
Metadata
Metadata
Assignees
Labels
3.13bugs and security fixesbugs and security fixestopic-free-threadingtype-featureA feature request or enhancementA feature request or enhancement