@@ -43,7 +43,7 @@ currently executing.
43
43
Example - is the main tasklet the current tasklet::
44
44
45
45
stackless.main == stackless.current
46
-
46
+
47
47
Example - is the current tasklet the main tasklet::
48
48
49
49
stackless.current.is_main == 1
@@ -68,13 +68,13 @@ The ``tasklet`` class
68
68
This class exposes the form of lightweight thread (the tasklet) provided by
69
69
|SLP |. Wrapping a callable object and arguments to pass into
70
70
it when it is invoked, the callable is run within the tasklet.
71
-
71
+
72
72
Tasklets are usually created in the following manner::
73
-
73
+
74
74
>>> stackless.tasklet(func)(1 , 2 , 3 , name = " test" )
75
-
75
+
76
76
The above code is equivalent to::
77
-
77
+
78
78
>>> t = stackless.tasklet()
79
79
>>> t.bind(func)
80
80
>>> t.setup(1 , 2 , 3 , name = " test" )
@@ -90,7 +90,7 @@ The ``tasklet`` class
90
90
91
91
Note that when an implicit :meth: `tasklet.insert ` is invoked, there is no need
92
92
to hold a reference to the created tasklet.
93
-
93
+
94
94
.. method :: tasklet.bind(func=None, args=None, kwargs=None)
95
95
96
96
Bind the tasklet to the given callable object, *func *::
@@ -111,10 +111,10 @@ The ``tasklet`` class
111
111
112
112
*func * can be None when providing arguments, in which case a previous call
113
113
to :meth: `tasklet.bind ` must have provided the function.
114
-
114
+
115
115
To clear the binding of a tasklet set all arguments to ``None ``. This
116
116
is especially useful, if you run a tasklet only partially::
117
-
117
+
118
118
>>> def func():
119
119
... try:
120
120
... ... # part 1
@@ -125,10 +125,10 @@ The ``tasklet`` class
125
125
>>> t = stackless.tasklet(func)()
126
126
>>> stackless.enable_softswitch(True)
127
127
>>> stackless.run() # execute part 1 of func
128
- >>> t.bind(None) # unbind func(). Don't execute the finally block
129
-
128
+ >>> t.bind(None) # unbind func(). Don't execute the finally block
129
+
130
130
If a tasklet is alive, it can be rebound only if the tasklet is
131
- not the current tasklet and if the tasklet is not scheduled and
131
+ not the current tasklet and if the tasklet is not scheduled and
132
132
if the tasklet is restorable. :meth: `bind ` raises :exc: `RuntimeError `,
133
133
if these conditions are not met.
134
134
@@ -139,12 +139,12 @@ The ``tasklet`` class
139
139
>>> t = stackless.tasklet()
140
140
>>> t.bind(func)
141
141
>>> t.setup(1 , 2 , name = " test" )
142
-
142
+
143
143
In most every case, programmers will instead pass the arguments and
144
144
callable into the tasklet constructor instead::
145
145
146
146
>>> t = stackless.tasklet(func)(1 , 2 , name = " test" )
147
-
147
+
148
148
Note that when tasklets have been bound to a callable object and
149
149
provided with arguments to pass to it, they are implicitly
150
150
scheduled and will be run in turn when the scheduler is next run.
@@ -168,9 +168,9 @@ The ``tasklet`` class
168
168
.. method :: tasklet.remove()
169
169
170
170
Remove a tasklet from the runnables queue.
171
-
171
+
172
172
.. note ::
173
-
173
+
174
174
If this tasklet has a non-trivial C-state attached, Stackless
175
175
will kill the tasklet when the containing thread terminates.
176
176
Since this will happen in some unpredictable order, it may cause unwanted
@@ -182,9 +182,9 @@ The ``tasklet`` class
182
182
If the tasklet is alive and not blocked on a channel, then it will be run
183
183
immediately. However, this behaves differently depending on whether
184
184
the tasklet is in the scheduler's chain of runnable tasklets.
185
-
185
+
186
186
Example - running a tasklet that is scheduled::
187
-
187
+
188
188
>>> def f(name):
189
189
... while True:
190
190
... c=stackless.current
@@ -206,7 +206,7 @@ The ``tasklet`` class
206
206
yields, the next tasklet in the chain is scheduled and so forth until the
207
207
tasklet that actually ran *t1 * - that is the main tasklet - is scheduled and
208
208
resumes execution.
209
-
209
+
210
210
If you were to run *t2 * instead of *t1 *, then we would have only seen the
211
211
output of *t2 * and *t3 *, because the tasklet calling :attr: `run ` is before
212
212
*t1 * in the chain.
@@ -226,7 +226,7 @@ The ``tasklet`` class
226
226
t2 id=36355504, next.id=36356016, main.id=36356016, main.scheduled=True
227
227
>>> t2.scheduled
228
228
True
229
-
229
+
230
230
While the ability to run a tasklet directly is useful on occasion, that
231
231
the scheduler is still involved and that this is merely directing its
232
232
operation in limited ways, is something you need to be aware of.
@@ -238,10 +238,10 @@ The ``tasklet`` class
238
238
the scheduling queue.
239
239
240
240
The target tasklet must belong to the same thread as the caller.
241
-
242
- Example - switch to a tasklet that is scheduled. Function f is defined as
241
+
242
+ Example - switch to a tasklet that is scheduled. Function f is defined as
243
243
in the previous example::
244
-
244
+
245
245
>>> t1 = stackless.tasklet(f)("t1")
246
246
>>> t2 = stackless.tasklet(f)("t2")
247
247
>>> t3 = stackless.tasklet(f)("t3")
@@ -259,16 +259,16 @@ The ``tasklet`` class
259
259
File "<stdin>", line 6, in f
260
260
KeyboardInterrupt
261
261
>>>
262
-
263
- What you see here is that the main tasklet was removed from the scheduler.
262
+
263
+ What you see here is that the main tasklet was removed from the scheduler.
264
264
Therefore the scheduler runs until it got interrupted by a keyboard interrupt.
265
265
266
266
.. method :: tasklet.raise_exception(exc_class, *args)
267
267
268
268
Raise an exception on the given tasklet. *exc_class * is required to be a
269
269
sub-class of :exc: `Exception `. It is instantiated with the given arguments
270
270
*args * and raised within the given tasklet.
271
-
271
+
272
272
In order to make best use of this function, you should be familiar with
273
273
how tasklets and the scheduler :ref: `deal with exceptions
274
274
<slp-exc-section>`, and the purpose of the :ref: `TaskletExit <slp-exc >`
@@ -312,7 +312,7 @@ The ``tasklet`` class
312
312
.. method :: tasklet.set_atomic(flag)
313
313
314
314
This method is used to construct a block of code within which the tasklet
315
- will not be auto-scheduled when preemptive scheduling. It is useful for
315
+ will not be auto-scheduled when preemptive scheduling. It is useful for
316
316
wrapping critical sections that should not be interrupted::
317
317
318
318
old_value = t.set_atomic(1)
@@ -353,8 +353,8 @@ The following (read-only) attributes allow tasklet state to be checked:
353
353
.. attribute :: tasklet.paused
354
354
355
355
This attribute is ``True `` when a tasklet is alive, but not scheduled or
356
- blocked on a channel. This state is entered after a :meth: `tasklet.bind ` with
357
- 2 or 3 arguments, a :meth: `tasklet.remove ` or by the main tasklet, when it
356
+ blocked on a channel. This state is entered after a :meth: `tasklet.bind ` with
357
+ 2 or 3 arguments, a :meth: `tasklet.remove ` or by the main tasklet, when it
358
358
is acting as a watchdog.
359
359
360
360
.. attribute :: tasklet.blocked
@@ -368,11 +368,11 @@ The following (read-only) attributes allow tasklet state to be checked:
368
368
369
369
.. attribute :: tasklet.restorable
370
370
371
- This attribute is ``True ``, if the tasklet can be completely restored by
372
- pickling/unpickling. If a tasklet is restorable, it is possible to continue
371
+ This attribute is ``True ``, if the tasklet can be completely restored by
372
+ pickling/unpickling. If a tasklet is restorable, it is possible to continue
373
373
running the unpickled tasklet from whatever point in execution it may be.
374
-
375
- All tasklets can be pickled for debugging/inspection
374
+
375
+ All tasklets can be pickled for debugging/inspection
376
376
purposes, but an unpickled tasklet might have lost runtime information (C stack).
377
377
For the tasklet to be runnable, it must not have lost runtime information
378
378
(C stack usage for instance).
@@ -416,12 +416,12 @@ The following attributes allow identification of tasklet place:
416
416
import stackless
417
417
def is_current_main(tasklet):
418
418
return tasklet is stackless.main
419
-
419
+
420
420
.. attribute :: tasklet.thread_id
421
421
422
422
This attribute is the id of the thread the tasklet belongs to. If its
423
423
thread has terminated, the attribute value is ``-1 ``.
424
-
424
+
425
425
The relationship between tasklets and threads is :doc: `covered elsewhere
426
426
<threads>`.
427
427
@@ -439,16 +439,16 @@ The following attributes allow a tasklets place in a chain to be identified:
439
439
440
440
The next tasklet in the chain that this tasklet is linked into.
441
441
442
- The following attributes are intended only for implementing debuggers,
443
- profilers, coverage tools and the like. Their behavior is part of the
444
- implementation platform, rather than part of the language definition,
442
+ The following attributes are intended only for implementing debuggers,
443
+ profilers, coverage tools and the like. Their behavior is part of the
444
+ implementation platform, rather than part of the language definition,
445
445
and thus may not be available in all |SLP | implementations.
446
446
447
447
.. attribute :: tasklet.trace_function
448
448
449
449
.. attribute :: tasklet.profile_function
450
450
451
- The trace / profile function of the tasklet. These attributes
451
+ The trace / profile function of the tasklet. These attributes
452
452
are the tasklet counterparts of the functions :func: `sys.settrace `,
453
453
:func: `sys.gettrace `, :func: `sys.setprofile ` and :func: `sys.getprofile `.
454
454
@@ -457,16 +457,16 @@ and thus may not be available in all |SLP| implementations.
457
457
Tasklet Life Cycle
458
458
^^^^^^^^^^^^^^^^^^
459
459
460
- Here is a somewhat simplified state chart that shows the life cycle of a
461
- tasklet instance. The chart does not show the nesting-level, the thread-id
462
- and the flags atomic, ignore-nesting, block-trap and restorable.
460
+ Here is a somewhat simplified state chart that shows the life cycle of a
461
+ tasklet instance. The chart does not show the nesting-level, the thread-id
462
+ and the flags atomic, ignore-nesting, block-trap and restorable.
463
463
464
464
.. image :: tasklet_state_chart.png
465
465
466
- Furthermore the diagram does not show the scheduler functions
467
- :func: `stackless.run `, :func: `stackless.schedule ` and
468
- :func: `stackless.schedule_remove() `. For the purpose of understanding the
469
- state transitions these functions are roughly equivalent to the following
466
+ Furthermore the diagram does not show the scheduler functions
467
+ :func: `stackless.run `, :func: `stackless.schedule ` and
468
+ :func: `stackless.schedule_remove() `. For the purpose of understanding the
469
+ state transitions these functions are roughly equivalent to the following
470
470
|PY | definitions::
471
471
472
472
def run():
@@ -476,9 +476,9 @@ state transitions these functions are roughly equivalent to the following
476
476
stackless.current.next.run()
477
477
main.switch()
478
478
stackless.tasklet(watchdog)().switch()
479
-
479
+
480
480
def schedule():
481
481
stackless.current.next.run()
482
-
482
+
483
483
def schedule_remove():
484
484
stackless.current.next.switch()
0 commit comments