Skip to content

gh-154562: Add ContextVar.thread_inheritable().#154564

Draft
nascheme wants to merge 1 commit into
python:mainfrom
nascheme:ctx_thread_inheritable_vars
Draft

gh-154562: Add ContextVar.thread_inheritable().#154564
nascheme wants to merge 1 commit into
python:mainfrom
nascheme:ctx_thread_inheritable_vars

Conversation

@nascheme

@nascheme nascheme commented Jul 23, 2026

Copy link
Copy Markdown
Member

Summary

Add contextvars.ContextVar.thread_inheritable(name, *, default), an alternative constructor for context variables whose bindings are inherited by new threading.Thread instances even when sys.flags.thread_inherit_context is false.

This gives libraries a middle ground between "threads inherit nothing" (the GIL-build default) and "threads inherit everything" (the -X thread_inherit_context=1 flag). A library converting module-level global state to context-local state can opt its own variables in to thread inheritance without requiring the application to enable the flag process-wide and without cooperation from the code that creates threads.

Behavior

  • When Thread.start() would otherwise start the thread with an empty context (flag false, no explicit context=), the new thread's context is instead initialized with the caller's current bindings of all thread-inheritable variables.
  • The seeded values are ordinary bindings: visible to copy_context(), independently settable in the child, and inherited transitively by threads the child starts.
  • Explicitly supplied contexts (Thread(context=...)) are unaffected, as are threads started by other means (_thread.start_new_thread(), C API).
  • When thread_inherit_context is true, a variable created this way behaves identically to a plain ContextVar, so the constructor is safe to use unconditionally.

Implementation

Each Context maintains a second HAMT holding the redundant subset of bindings belonging to thread-inheritable variables, kept in sync by ContextVar.set()/reset(). Thread.start() uses a private _contextvars._thread_start_context() factory that creates the child context directly from that subset, so thread startup cost is independent of how many variables are bound and unchanged when no inheritable variables exist (the subset is empty and shared).

ContextVar grows a var_thread_inheritable flag set only by the new classmethod; the plain constructor is unchanged. PyContext is publicly opaque, so the extra field does not affect the public C API.

Context variables created this way will automatically be inherited by
the context for new threads, regardless of the setting of
`thread_inherit_context`.
@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33732525 | 📁 Comparing c29fef5 against main (66e313f)

  🔍 Preview build  

5 files changed · ± 5 modified

± Modified

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant