8000 Stackless issue #139: add pickle-flags to PyStacklessState · akruis/cpython@99ac643 · GitHub
[go: up one dir, main page]

Skip to content

Commit 99ac643

Browse files
committed
Stackless issue python#139: add pickle-flags to PyStacklessState
Add the flags and methods stackless.pickle_flags() and stackless.pickle_flags_default() to get or set them. Currently only one flag is defined in prickelpit.h. It will be used by the next commit.
1 parent 413fabd commit 99ac643

File tree

8 files changed

+399
-59
lines changed

8 files changed

+399
-59
lines changed

Doc/library/stackless/stackless.rst

Lines changed: 120 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
==================================================
33

44
.. module:: stackless
5-
:synopsis: Access the enhanced functionality provided by Stackless
5+
:synopsis: Access the enhanced functionality provided by |SLP|
66

77
.. moduleauthor:: Christian Tismer <tismer@stackless.com>
88
.. sectionauthor:: Richard Tew <richard.m.tew@gmail.com>
@@ -21,6 +21,22 @@ the enhanced functionality provided by |SLP|.
2121
threads.rst
2222
pickling.rst
2323

24+
---------
25+
Constants
26+
---------
27+
28+
.. data:: PICKLEFLAGS_PRESERVE_TRACING_STATE
29+
30+
This constant defines an option flag for the function
31+
:func:`pickle_flags`.
32+
33+
If this flag is set, a pickled tasklet contains
34+
information about the tracing and/or profiling state of the tasklet.
35+
Usually there's no need to set this flag.
36+
37+
.. versionadded:: 3.7
38+
39+
2440
---------
2541
Functions
2642
---------
@@ -42,36 +58,36 @@ The main scheduling related functions:
4258
The optional argument *timeout* is primarily used to run the scheduler
4359
in a different manner, providing pre-emptive scheduling. A non-zero
4460
value indicates that as each tasklet is given a chance to run, it
45-
should only be allowed to run as long as the number of
46-
:mod:`|PY| virtual instructions <dis>` are below this value. If a
61+
should only be allowed to run as long as the number of
62+
|PY| :mod:`virtual instructions <dis>` are below this value. If a
4763
tasklet hits this limit, then it is interrupted and the scheduler
4864
exits returning the now no longer scheduled tasklet to the caller.
49-
65+
5066
Example - run until 1000 opcodes have been executed::
51-
67+
5268
interrupted_tasklet = stackless.run(1000)
5369
# interrupted_tasklet is no longer scheduled, reschedule it.
5470
interrupted_tasklet.insert()
5571
# Now run your custom logic.
5672
...
57-
58-
The optional argument *threadblock* affects the way Stackless works when
73+
74+
The optional argument *threadblock* affects the way |SLP| works when
5975
channels are used for communication between threads. Normally when
6076
the scheduler has no remaining tasklets to run besides the current one,
6177
the main tasklet is reawakened. By engaging this option, if there are other
6278
running |PY| threads then the current one will instead block expecting
6379
them to eventually wake it up.
64-
80+
6581
The optional argument *soft* affects how pre-emptive scheduling behaves.
6682
When a pre-emptive interruption would normally occur, instead of
6783
interrupting and returning the running tasklet, the scheduler exits at
6884
the next convenient scheduling moment.
69-
85+
7086
The optional argument *ignore_nesting* affects the behaviour of the
7187
attribute :attr:`tasklet.nesting_level` on individual tasklets. If set,
7288
interrupts are allowed at any interpreter nesting level, causing the
7389
tasklet-level attribute to be ignored.
74-
90+
7591
The optional argument *totaltimeout* affects how pre-emptive scheduling
7692
behaves. Normally the scheduler is interrupted when any given
7793
tasklet has been running for *timeout* instructions. If a value is
@@ -87,7 +103,7 @@ The main scheduling related functions:
87103
inner application modifying the outer behaviour.
88104

89105
.. note::
90-
106+
91107
The most common use of this function is to call it either without
92108
arguments, or with a value for *timeout*.
93109

@@ -96,20 +112,20 @@ The main scheduling related functions:
96112
Yield execution of the currently running tasklet. When called, the tasklet
97113
is blocked and moved to the end of the chain of runnable tasklets. The
98114
next tasklet in the chain is executed next.
99-
115+
100116
If your application employs cooperative scheduling and you do not use
101117
custom yielding mechanisms built around channels, you will most likely
102118
call this in your tasklets.
103119

104120
Example - typical usage of :func:`schedule`::
105-
121+
106122
stackless.schedule()
107-
123+
108124
As illustrated in the example, the typical use of this function ignores
109125
both the optional argument *retval* and the return value. Note that as
110126
the variable name *retval* hints, the return value is the value of the
111127
optional argument.
112-
128+
113129
.. function:: schedule_remove(retval=stackless.current)
114130

115131
Yield execution of the currently running tasklet. When called, the
@@ -120,15 +136,15 @@ The main scheduling related functions:
120136
build your own yielding primitive without using channels. This is where
121137
the otherwise ignored optional argument *retval* and the return value
122138
are useful.
123-
139+
124140
:attr:`tasklet.tempval` is used to store the value to be returned, and
125141
as expected, when this function is called it is set to *retval*. Custom
126142
utility functions can take advantage of this and set a new value for
127143
:attr:`tasklet.tempval` before reinserting the tasklet back into the
128144
scheduler.
129-
145+
130146
Example - a utility function::
131-
147+
132148
def wait_for_result():
133149
waiting_tasklets.append(stackless.current)
134150
return stackless.schedule_remove()
@@ -157,59 +173,59 @@ Callback related functions:
157173
in *callable* being called. Setting a value of ``None`` will result in the
158174
callback being disabled. The function returns the previous channel callback or
159175
``None`` if none was installed.
160-
176+
161177
Example - installing a callback::
162-
178+
163179
def channel_cb(channel, tasklet, sending, willblock):
164180
pass
165-
181+
166182
stackless.set_channel_callback(channel_cb)
167183

168184
The *channel* callback argument is the channel on which the action is
169185
being performed.
170-
186+
171187
The *tasklet* callback argument is the tasklet that is performing the
172188
action on *channel*.
173189

174190
The *sending* callback argument is an integer, a non-zero value of which
175191
indicates that the channel action is a send rather than a receive.
176-
192+
177193
The *willblock* callback argument is an integer, a non-zero value of which
178194
indicates that the channel action will result in *tasklet* being blocked
179195
on *channel*.
180-
196+
181197
.. function:: get_channel_callback()
182198

183-
Get the current global channel callback. The function returns the
199+
Get the current global channel callback. The function returns the
184200
current channel callback or ``None`` if none was installed.
185201

186202
.. function:: set_schedule_callback(callable)
187203

188204
Install a callback for scheduling. Every scheduling event, whether
189205
explicit or implicit, will result in *callable* being called. The function
190206
returns the previous channel callback or ``None`` if none was installed.
191-
207+
192208
Example - installing a callback::
193-
209+
194210
def schedule_cb(prev, next):
195211
pass
196-
212+
197213
stackless.set_schedule_callback(callable)
198-
214+
199215
The *prev* callback argument is the tasklet that was just running.
200-
216+
201217
The *next* callback argument is the tasklet that is going to run now.
202-
218+
203219
.. note::
204-
220+
205221
During the execution of the scheduler callback the return value
206-
of :func:`getcurrent` and the value of :attr:`current` are
222+
of :func:`getcurrent` and the value of :attr:`current` are
207223
implementation defined. You are not allowed to execute any methods, that
208224
change the state of stackless for the current thread.
209225

210226
.. function:: get_schedule_callback()
211227

212-
Get the current global schedule callback. The function returns the
228+
Get the current global schedule callback. The function returns the
213229
current schedule callback or ``None`` if none was installed.
214230

215231
Scheduler state introspection related functions:
@@ -218,19 +234,19 @@ Scheduler state introspection related functions:
218234

219235
Return a tuple containing the threads main tasklet, current tasklet and
220236
run-count.
221-
237+
222238
Example::
223-
239+
224240
main_tasklet, current_tasklet, runcount = get_thread_info(thread_id)
225241

226242
.. function:: getcurrent()
227243

228244
Return the currently executing tasklet of this thread.
229-
245+
230246
.. function:: getmain()
231247

232248
Return the main tasklet of this thread.
233-
249+
234250
.. function:: getruncount()
235251

236252
Return the number of currently runnable tasklets.
@@ -250,23 +266,76 @@ Scheduler state introspection related functions:
250266
finally:
251267
stackless.switch_trap(-1)
252268

269+
Pickling related functions:
270+
271+
.. function:: pickle_flags_default(new_default=-1, mask=-1)
272+
273+
Get and set the per interpreter default value for pickle-flags.
274+
275+
A number of option flags control various aspects of |SLP| pickling behaviour.
276+
See :func:`pickle_flags` for details.
277+
278+
Whenever |PY| initialises a thread state, it copies the default-value to
279+
the thread state. Use function :func:`pickle_flags` to get and
280+
set the flags of the current thread only.
281+
282+
:param new_default: The new default value for pickle-flags
283+
:type new_default: int
284+
:param mask: A bit mask, that indicates the valid bits in argument "new_default"
285+
:type mask: int
286+
:return: the previous default value for pickle-flags
287+
:rtype: int
288+
:raises ValueError: if you try to set undefined bits
289+
290+
To inquire the value without changing it, omit the arguments (or set them to -1).
291+
292+
.. versionadded:: 3.7
293+
294+
295+
.. function:: pickle_flags(new_flags=-1, mask=-1)
296+
297+
Get and set per thread pickle-flags.
298+
299+
A number of option flags control various aspects of |SLP| pickling behaviour.
300+
Symbolic names for the flags are supplied as module constants, which can be
301+
:ref:`bitwise ORed <bitwise>` together and passed to this function.
302+
303+
Currently the following pickle option flags are defined:
304+
305+
- bit 0: :const:`PICKLEFLAGS_PRESERVE_TRACING_STATE`.
306+
307+
All other bits must be set to 0.
308+
309+
:param new_flags: The new value for pickle-flags of the current thread
310+
:type new_flags: int
311+
:param mask: A bit mask, that indicates the valid bits in argument "new_flags"
312+
:type mask: int
313+
:return: the previous value of pickle-flags of the current thread
314+
:rtype: int
315+
:raises ValueError: if you try to set undefined bits
316+
317+
To inquire the value without changing it, omit the arguments (or set them to -1).
318+
319+
.. versionadded:: 3.7
320+
321+
253322
Debugging related functions:
254323

255324
.. function:: enable_softswitch(flag)
256325

257-
Control the switching behaviour.
326+
Control the switching behaviour.
258327
Tasklets can be either switched by moving C stack slices around
259328
or by avoiding stack changes at all. The latter is only possible
260329
in the top interpreter level. This flag exists once for the whole process.
261330
For inquiry only, use 'None' as the flag.
262331
By default, soft switching is enabled.
263-
332+
264333
Example - safely disabling soft switching::
265-
334+
266335
old_value = stackless.enable_softswitch(False)
267336
# Logic executed without soft switching.
268337
enable_softswitch(old_value)
269-
338+
270339
.. note::
271340

272341
Disabling soft switching in this manner is exposed for timing and
@@ -297,22 +366,22 @@ Attributes
297366
Example - usage::
298367

299368
>>> stackless.runcount
300-
1
369+
1
301370

302371
.. note::
303-
372+
304373
The minimum value of :attr:`runcount` will be ``1``, as the calling
305374
tasklet will be included.
306375

307376
Equivalent function: :func:`getruncount`.
308377

309-
378+
310379
.. attribute:: threads
311380

312381
A list of all thread ids, starting with the id of the main thread.
313382

314383
Example - usage::
315-
384+
316385
>>> stackless.threads
317386
[5148]
318387

@@ -323,10 +392,10 @@ Attributes
323392
information about the tracing and/or profiling state of the tasklet.
324393
By default :attr:`pickle_with_tracing_state` is `False`. Usually
325394
there's no need to change this value.
326-
395+
327396
If you need to set this attribute on a per thread base,
328397
you can redefine the attribute as a thread local property::
329-
398+
330399
>>> import stackless
331400
>>> import threading
332401
>>> stackless._pickle_with_tracing = threading.local()
@@ -348,9 +417,9 @@ Exceptions
348417
This exception is used to silently kill a tasklet. It should not be
349418
caught by your code, and along with other important exceptions like
350419
:exc:`SystemExit`, be propagated up to the scheduler.
351-
420+
352421
The following use of the ``except`` clause should be avoided::
353-
422+
354423
try:
355424
some_function()
356425
except:
@@ -360,7 +429,7 @@ Exceptions
360429
:exc:`TaskletExit`. Unless you guarantee you actually raise the exceptions
361430
that should reach the scheduler, you are better to use ``except`` in the
362431
following manner::
363-
432+
364433
try:
365434
some_function()
366435
except Exception:

Lib/stackless.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ def __reduce__():
2121
def __reduce_ex__(*args):
2222
return "stackless"
2323

24+
PICKLEFLAGS_PRESERVE_TRACING_STATE = 1
25+
2426
# Backwards support for unpickling older pickles, even from 2.7
2527
from _stackless import _wrap
2628
sys.modules["stackless._wrap"] = _wrap

Stackless/changelog.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ What's New in Stackless 3.X.X?
99

1010
*Release date: 20XX-XX-XX*
1111

12+
- https://github.com/stackless-dev/stackless/issues/139
13+
New functions stackless.pickle_flags() and stackless.pickle_flags_default().
14+
They can be used to control pickling of certain objects.
15+
1216
- https://github.com/stackless-dev/stackless/issues/175
1317
Cleanup of the Stackless C-API: Including stackless_api.h in an extension
1418
module no longer defines internal stuff. Additionally I moved test code

0 commit comments

Comments
 (0)
0