Skip to main content

Include/internal/pycore_context.h

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_context.h

This header exposes the concrete struct layouts for the three PEP 567 context-variable objects: PyContext (a running context snapshot), PyContextVar (a per-variable descriptor), and PyContextToken (a revert handle). All three are opaque in the public API; only code built with Py_BUILD_CORE can see the fields.

The key data structure behind PyContext is a persistent, hash-array-mapped trie (PyHamtObject, aliased as ctx_vars). When a thread enters a context it snapshots the current HAMT root. On exit, ctx_prev is used to restore the previous context. This copy-on-write design lets nested contextvars.copy_context() calls share structure without defensive copying.

PyContextVar optionally carries an inline single-entry cache (var_cached, var_cached_tsid, var_cached_tsver) that is active only in the GIL build. In the free-threaded (Py_GIL_DISABLED) build those fields are omitted and every lookup goes through the HAMT directly.

Map

LinesSymbolRolegopy
14_PyContext_InitInterpreter-level init for the context subsystemnot ported
19-21_PyContextTokenMissingSentinel object returned when a var has no valuenot ported
23-29_pycontextobjectFull layout of PyContext: prev-link, HAMT, weakrefs, entered flagnot ported
32-42_pycontextvarobjectLayout of PyContextVar: name, default, optional GIL-only cache, hashnot ported
45-51_pycontexttokenobjectLayout of PyContextToken: owning context, var, old value, used flagnot ported
56_PyContext_NewHamtForTestsTest helper that exposes a raw HAMT snapshotnot ported

Reading

Guard and imports (lines 1 to 8)

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_context.h#L1-8

The standard Py_BUILD_CORE guard prevents accidental inclusion from extension code. The only dependency is pycore_structs.h, which provides the forward declarations for PyContext, PyContextVar, and PyContextToken used throughout the rest of the interpreter.

#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif
#include "pycore_structs.h"

Context object layout (lines 23 to 29)

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_context.h#L23-29

ctx_vars is a pointer to the HAMT root representing the entire variable mapping at the moment this context is active. ctx_prev forms a singly-linked stack so PyContext_Exit can walk back to the caller's context. ctx_entered is a boolean guard that prevents re-entering an already-active context.

struct _pycontextobject {
PyObject_HEAD
PyContext *ctx_prev;
PyHamtObject *ctx_vars;
PyObject *ctx_weakreflist;
int ctx_entered;
};

ContextVar layout and GIL cache (lines 32 to 42)

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_context.h#L32-42

The optional var_cached / var_cached_tsid / var_cached_tsver triplet is a thread-state-level single-entry cache. var_cached_tsid identifies which PyThreadState owns the cached value and var_cached_tsver is a version counter that is invalidated on every contextvars.Context.run() entry. In the free-threaded build the fields are compiled away entirely.

struct _pycontextvarobject {
PyObject_HEAD
PyObject *var_name;
PyObject *var_default;
#ifndef Py_GIL_DISABLED
PyObject *var_cached;
uint64_t var_cached_tsid;
uint64_t var_cached_tsver;
#endif
Py_hash_t var_hash;
};

Token layout (lines 45 to 51)

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_context.h#L45-51

A token records the variable it belongs to (tok_var), the context in which set() was called (tok_ctx), and tok_oldval, which is the value that should be restored on reset(). tok_used is set to 1 after reset() fires so the token cannot be reused.

struct _pycontexttokenobject {
PyObject_HEAD
PyContext *tok_ctx;
PyContextVar *tok_var;
PyObject *tok_oldval;
int tok_used;
};

gopy mirror

Not yet ported.