@@ -609,27 +609,27 @@ Design requirements were
609
609
4. Enable the integration of tasklet-based co-routines into the :mod: `asyncio ` framework.
610
610
This is an obvious application which involves context variables and tasklets.
611
611
612
- Now each tasklet object has a private context attribute, which is either undefined (``NULL ``) or a
613
- :class: `~contextvars.Context ` object. The design goals have some consequences:
612
+ Now each tasklet object has it own private context attribute. The design goals have some consequences:
614
613
615
614
* The active :class: `~contextvars.Context ` object of a thread (as defined by the |PPL |)
616
615
is the context of the :attr: `~stackless.current ` tasklet. This implies that a tasklet switch,
617
616
switches the active context of the thread.
618
617
619
618
* In accordance with the design decisions made in :pep: `567 ` the context of a tasklet can't be
620
- accessed directly, but you can use the method :meth: `tasklet.context_run ` to run arbitrary code
619
+ accessed directly [ #f1 ]_ , but you can use the method :meth: `tasklet.context_run ` to run arbitrary code
621
620
in this context. For instance ``tasklet.context_run(contextvars.copy_context()) `` returns a copy
622
621
of the context.
623
622
The attribute :attr: `tasklet.context_id ` can be used to test, if two tasklets share the context.
624
623
625
- * A tasklet, whose context is undefined must behave identically to a tasklet, whose context is an
626
- empty :class: `~contextvars.Context ` object. [#f1 ]_ Therefore the |PY | API provides no way to distinguish
627
- both states.
628
-
629
- * Whenever the context of a tasklet is to be shared with another tasklet and the context is initially
630
- undefined, it must be set to a newly created :class: `~contextvars.Context ` object beforehand.
624
+ * If you use the C-API, the context attribute of a tasklet is stored in the field *context * of the structure
625
+ :c:type: `PyTaskletObject ` or :c:type: `PyThreadState `. This field is is either undefined (``NULL ``) or a pointer to a
626
+ :class: `~contextvars.Context ` object.
627
+ A tasklet, whose *context * is ``NULL `` **must ** behave identically to a tasklet, whose context is an
628
+ empty :class: `~contextvars.Context ` object [#f2 ]_. Therefore the |PY | API provides no way to distinguish
629
+ both states. Whenever the context of a tasklet is to be shared with another tasklet and `tasklet->context `
630
+ is initially `NULL `, it must be set to a newly created :class: `~contextvars.Context ` object beforehand.
631
631
This affects the methods :meth: `~tasklet.context_run `, :meth: `~tasklet.__init__ `, :meth: `~tasklet.bind `
632
- and :meth: `~tasklet.__setstate__ `.
632
+ and :meth: `~tasklet.__setstate__ ` as well as the attribute :attr: ` tasklet.context_id ` .
633
633
634
634
* If the state of a tasklet changes from *not alive * to *bound * or to *alive * (methods :meth: `~tasklet.__init__ `,
635
635
:meth: `~tasklet.bind ` or :meth: `~tasklet.__setstate__ `), the context
@@ -645,7 +645,11 @@ Now each tasklet object has a private context attribute, which is either undefin
645
645
646
646
.. rubric :: Footnotes
647
647
648
- .. [#f1 ] Setting a context variable to a non default value sets a previously undefined
649
- context attribute to a newly created :class: `~contextvars.Context ` object. This can happen anytime in a
648
+ .. [#f1 ] Not exactly true. The return value of :meth: `tasklet.__reduce_ex__ ` can contain references to class
649
+ :class: `contextvars.Context `, but it is strongly discouraged, to use them for any other purpose
650
+ than pickling.
651
+
652
+ .. [#f2 ] Setting a context variable to a non default value changes the value of the field *context * from ``NULL ``
653
+ to a pointer to a newly created :class: `~contextvars.Context ` object. This can happen anytime in a
650
654
library call. Therefore any difference between an undefined context and an empty context causes ill defined
651
655
behavior.
0 commit comments