gh-154562: Add ContextVar.thread_inheritable().#154564
Draft
nascheme wants to merge 1 commit into
Draft
Conversation
Context variables created this way will automatically be inherited by the context for new threads, regardless of the setting of `thread_inherit_context`.
Documentation build overview
5 files changed ·
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add
contextvars.ContextVar.thread_inheritable(name, *, default), an alternative constructor for context variables whose bindings are inherited by newthreading.Threadinstances even whensys.flags.thread_inherit_contextis false.This gives libraries a middle ground between "threads inherit nothing" (the GIL-build default) and "threads inherit everything" (the
-X thread_inherit_context=1flag). 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
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.copy_context(), independently settable in the child, and inherited transitively by threads the child starts.Thread(context=...)) are unaffected, as are threads started by other means (_thread.start_new_thread(), C API).thread_inherit_contextis true, a variable created this way behaves identically to a plainContextVar, so the constructor is safe to use unconditionally.Implementation
Each
Contextmaintains a second HAMT holding the redundant subset of bindings belonging to thread-inheritable variables, kept in sync byContextVar.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).ContextVargrows avar_thread_inheritable flagset only by the new classmethod; the plain constructor is unchanged.PyContextis publicly opaque, so the extra field does not affect the public C API.