Skip to content

Commit f3a3d97

Browse files
author
Anselm Kruis
committed
Migrate the documentation of the Stackless C-API to the new Sphinx syntax.
Use c:function instead cfunction and the like. (grafted from bb7a134d72cc6c4528078476c9d3e061e79b28ab)
1 parent 938fb53 commit f3a3d97

File tree

1 file changed

+343
-0
lines changed

1 file changed

+343
-0
lines changed

Doc/c-api/stackless.rst

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
.. highlightlang:: c
2+
3+
.. comment: affected files: data\refcounts.dat
4+
.. comment: affected files: c-api\stackless.rst
5+
.. comment: to do: link c-api\stackless.rst in somewhere
6+
.. comment: to do: generate new docs
7+
8+
Tasklets
9+
--------
10+
11+
.. c:function:: PyTaskletObject *PyTasklet_New(PyTypeObject *type, PyObject *func)
12+
13+
Return a new tasklet object. *type* must be derived from :c:type:`PyTasklet_Type`
14+
or *NULL*. *func* must be a callable object (normal use-case) or *NULL*, if the
15+
tasklet is being used via capture().
16+
17+
.. todo: in the case where NULL is returned and slp_ensure_linkage fails no
18+
exception is set, which is in contrast elsewhere in the function.
19+
20+
.. c:function:: int PyTasklet_Setup(PyTaskletObject *task, PyObject *args, PyObject *kwds)
21+
22+
Binds a tasklet function to parameters, making it ready to run and inserts in
23+
into the runnables queue. Returns ``0`` if successful or ``-1`` in the case of failure.
24+
25+
.. c:function:: int PyTasklet_Run(PyTaskletObject *task)
26+
27+
Forces *task* to run immediately. Returns ``0`` if successful, and ``-1`` in the
28+
case of failure.
29+
30+
.. c:function:: int PyTasklet_Run_nr(PyTaskletObject *task)
31+
32+
Forces *task* to run immediately, soft switching if possible. Returns ``1`` if
33+
the call soft switched, ``0`` if the call hard switched and -1 in the case of
34+
failure.
35+
36+
.. c:function:: int PyTasklet_Remove(PyTaskletObject *task)
37+
38+
Removes *task* from the runnables queue. Be careful! If this tasklet has a C
39+
stack attached, you need to either resume running it or kill it. Just dropping
40+
it might give an inconsistent system state. Returns ``0`` if successful, and
41+
``-1`` in the case of failure.
42+
43+
.. c:function:: int PyTasklet_Insert(PyTaskletObject *task)
44+
45+
Insert *task* into the runnables queue, if it isn't already there. If it is
46+
blocked or dead, the function returns ``-1`` and a :exc:`RuntimeError` is raised.
47+
48+
.. c:function:: PyObject *PyTasklet_Become(PyTaskletObject *self, PyObject *retval)
49+
50+
Use of this API function is undocumented and unrecommended.
51+
52+
.. deprecated:: 2.5
53+
Proved problematic in production use and are pending removal.
54+
55+
.. c:function:: PyObject* PyTasklet_Capture(PyTaskletObject *self, PyObject *retval)
56+
57+
Use of this API function is undocumented and unrecommended.
58+
59+
.. deprecated:: 2.5
60+
Proved problematic in production use and are pending removal.
61+
62+
.. c:function:: int PyTasklet_RaiseException(PyTaskletObject *self, PyObject *klass, PyObject *args)
63+
64+
Raises an instance of the *klass* exception on the *self* tasklet. *klass* must
65+
be a subclass of :exc:`Exception`. Returns ``1`` if the call soft switched, ``0``
66+
if the call hard switched and ``-1`` in the case of failure.
67+
68+
.. note:: Raising :exc:`TaskletExit` on a tasklet can be done to silently kill
69+
it, see :c:func:`PyTasklet_Kill`.
70+
71+
.. c:function:: int PyTasklet_Kill(PyTaskletObject *self)
72+
73+
Raises :exc:`TaskletExit` on tasklet *self*. This should result in *task* being
74+
silently killed. Returns ``1`` if the call soft switched, ``0`` if the call hard
75+
switched and ``-1`` in the case of failure.
76+
77+
.. c:function:: int PyTasklet_GetAtomic(PyTaskletObject *task)
78+
79+
Returns ``1`` if *task* is atomic, otherwise ``0``.
80+
81+
.. c:function:: int PyTasklet_SetAtomic(PyTaskletObject *task, int flag)
82+
83+
Returns ``1`` if *task* is currently atomic, otherwise ``0``. Sets the
84+
atomic attribute to the logical value of *flag*.
85+
86+
.. c:function:: int PyTasklet_GetIgnoreNesting(PyTaskletObject *task)
87+
88+
Returns ``1`` if *task* ignores its nesting level when choosing whether to
89+
auto-schedule it, otherwise ``0``.
90+
91+
.. c:function:: int PyTasklet_SetIgnoreNesting(PyTaskletObject *task, int flag)
92+
93+
Returns the existing value of the *ignore_nesting* attribute for the tasklet
94+
*task*, setting it to the logical value of *flag*. If true, the tasklet may
95+
be auto-scheduled even if its *nesting_level* is > ``0``.
96+
97+
.. c:function:: int PyTasklet_GetBlockTrap(PyTaskletObject *task)
98+
99+
Returns ``1`` if *task* is designated as not being allowed to be blocked on a
100+
channel, otherwise ``0``.
101+
102+
.. c:function:: void PyTasklet_SetBlockTrap(PyTaskletObject *task, int value)
103+
104+
Returns ``1`` if *task* was already designated as not being allowed to be blocked
105+
on a channel, otherwise ``0``. This attribute is set to the logical value of
106+
*value*.
107+
108+
.. c:function:: PyObject *PyTasklet_GetFrame(PyTaskletObject *task)
109+
110+
Returns the current frame that *task* is executing in, or *NULL*
111+
112+
.. c:function:: int PyTasklet_IsMain(PyTaskletObject *task)
113+
114+
Returns ``1`` if *task* is the main tasklet, otherwise ``0``.
115+
116+
.. c:function:: int PyTasklet_IsCurrent(PyTaskletObject *task)
117+
118+
Returns ``1`` if *task* is the current tasklet, otherwise ``0``.
119+
120+
.. c:function:: int PyTasklet_GetRecursionDepth(PyTaskletObject *task)
121+
122+
Return the current recursion depth of *task*.
123+
124+
.. c:function:: int PyTasklet_GetNestingLevel(PyTaskletObject *task)
125+
126+
Return the current nesting level of *task*.
127+
128+
.. c:function:: int PyTasklet_Alive(PyTaskletObject *task)
129+
130+
Returns ``1`` if *task* is alive (has an associated frame), otherwise
131+
``0`` if it is dead.
132+
133+
.. c:function:: int PyTasklet_Paused(PyTaskletObject *task)
134+
135+
Returns ``1`` if *task* is paused, otherwise ``0``. A tasklet is paused if it is
136+
alive, but not scheduled or blocked on a channel.
137+
138+
.. c:function:: int PyTasklet_Scheduled(PyTaskletObject *task)
139+
140+
Returns ``1`` if *task* is scheduled, otherwise ``0``. In the context of this
141+
function a tasklet is considered to be scheduled if it is alive, and in the
142+
scheduler runnables list or blocked on a channel.
143+
144+
.. c:function:: int PyTasklet_Restorable(PyTaskletObject *task)
145+
146+
Returns ``1`` if *task* can be fully unpickled, otherwise ``0``. A tasklet can
147+
be pickled whether it is fully restorable or not for the purposes of debugging
148+
and introspection. A tasklet that has been hard-switched cannot be fully
149+
pickled, for instance.
150+
151+
Channels
152+
--------
153+
154+
.. c:function:: PyChannelObject* PyChannel_New(PyTypeObject *type)
155+
156+
Return a new channel object, or *NULL* in the case of failure. *type* must be
157+
derived from :c:type:`PyChannel_Type` or be *NULL*, otherwise a :exc:`TypeError`
158+
is raised.
159+
160+
.. c:function:: int PyChannel_Send(PyChannelObject *self, PyObject *arg)
161+
162+
Send *arg* on the channel *self*. Returns ``0`` if the operation was
163+
successful, or ``-1`` in the case of failure.
164+
165+
.. c:function:: int PyChannel_Send_nr(PyChannelObject *self, PyObject *arg)
166+
167+
Send *arg* on the channel *self*, soft switching if possible. Returns ``1`` if
168+
the call soft switched, ``0`` if the call hard switched and -1 in the case of
169+
failure.
170+
171+
.. c:function:: PyObject *PyChannel_Receive(PyChannelObject *self)
172+
173+
Receive on the channel *self*. Returns a |PY| object if the operation was
174+
successful, or *NULL* in the case of failure.
175+
176+
.. c:function:: PyObject *PyChannel_Receive_nr(PyChannelObject *self)
177+
178+
Receive on the channel *self*, soft switching if possible. Returns a |PY|
179+
object if the operation was successful, :c:type:`Py_UnwindToken` if a soft switch
180+
occurred, or *NULL* in the case of failure.
181+
182+
.. c:function:: int PyChannel_SendException(PyChannelObject *self, PyObject *klass, PyObject *value)
183+
184+
Returns ``0`` if successful or ``-1`` in the case of failure. An instance of the
185+
exception type *klass* is raised on the first tasklet blocked on channel *self*.
186+
187+
.. c:function:: PyObject *PyChannel_GetQueue(PyChannelObject *self)
188+
189+
Returns the first tasklet in the channel *self*'s queue, or *NULL* in the case
190+
the queue is empty.
191+
192+
.. c:function:: void PyChannel_Close(PyChannelObject *self)
193+
194+
Marks the channel *self* as closing. No further tasklets can be blocked on the
195+
it from this point, unless it is later reopened.
196+
197+
.. c:function:: void PyChannel_Open(PyChannelObject *self)
198+
199+
Reopens the channel *self*. This allows tasklets to once again send and receive
200+
on it, if those operations would otherwise block the given tasklet.
201+
202+
.. c:function:: int PyChannel_GetClosing(PyChannelObject *self)
203+
204+
Returns ``1`` if the channel *self* is marked as closing, otherwise ``0``.
205+
206+
.. c:function:: int PyChannel_GetClosed(PyChannelObject *self)
207+
208+
Returns ``1`` if the channel *self* is marked as closing and there are no tasklets
209+
blocked on it, otherwise ``0``.
210+
211+
.. c:function:: int PyChannel_GetPreference(PyChannelObject *self)
212+
213+
Returns the current scheduling preference value of *self*. See
214+
:attr:`channel.preference`.
215+
216+
.. c:function:: void PyChannel_SetPreference(PyChannelObject *self, int val)
217+
218+
Sets the current scheduling preference value of *self*. See
219+
:attr:`channel.preference`.
220+
221+
.. c:function:: int PyChannel_GetScheduleAll(PyChannelObject *self)
222+
223+
Gets the *schedule_all* override flag for *self*. See
224+
:attr:`channel.schedule_all`.
225+
226+
.. c:function:: void PyChannel_SetScheduleAll(PyChannelObject *self, int val)
227+
228+
Sets the *schedule_all* override flag for *self*. See
229+
:attr:`channel.schedule_all`.
230+
231+
.. c:function:: int PyChannel_GetBalance(PyChannelObject *self)
232+
233+
Gets the balance for *self*. See :attr:`channel.balance`.
234+
235+
stackless module
236+
----------------
237+
238+
.. c:function:: PyObject *PyStackless_Schedule(PyObject *retval, int remove)
239+
240+
Suspend the current tasklet and schedule the next one in the cyclic chain.
241+
if remove is nonzero, the current tasklet will be removed from the chain.
242+
retval = success NULL = failure
243+
244+
.. c:function:: PyObject *PyStackless_Schedule_nr(PyObject *retval, int remove)
245+
246+
retval = success NULL = failure
247+
retval == Py_UnwindToken: soft switched
248+
249+
.. c:function:: int PyStackless_GetRunCount()
250+
251+
get the number of runnable tasks of the current thread, including the current one.
252+
-1 = failure
253+
254+
.. c:function:: PyObject *PyStackless_GetCurrent()
255+
256+
Get the currently running tasklet, that is, "yourself".
257+
258+
.. c:function:: PyObject *PyStackless_RunWatchdog(long timeout)
259+
260+
Runs the scheduler until there are no tasklets remaining within it, or until
261+
one of the scheduled tasklets runs for *timeout* VM instructions without
262+
blocking. Returns *None* if the scheduler is empty, a tasklet object if that
263+
tasklet timed out, or *NULL* in the case of failure. If a timed out tasklet
264+
is returned, it should be killed or reinserted.
265+
266+
This function can only be called from the main tasklet.
267+
During the run, main is suspended, but will be invoked
268+
after the action. You will write your exception handler
269+
here, since every uncaught exception will be directed
270+
to main.
271+
272+
.. c:function:: PyObject *PyStackless_RunWatchdogEx(long timeout, int flags)
273+
274+
Wraps :c:func:`PyStackless_RunWatchdog`, but allows its behaviour to be
275+
customised by the value of *flags* which may contain any of the following
276+
bits:
277+
278+
``Py_WATCHDOG_THREADBLOCK``
279+
Allows a thread to block if it runs out of tasklets. Ideally
280+
it will be awakened by other threads using channels which its
281+
blocked tasklets are waiting on.
282+
283+
``Py_WATCHDOG_SOFT``
284+
Instead of interrupting a tasklet, we wait until the
285+
next tasklet scheduling moment to return. Always returns
286+
*Py_None*, as everything is in order.
287+
288+
``Py_WATCHDOG_IGNORE_NESTING``
289+
Allows interrupts at all levels, effectively acting as
290+
though the *ignore_nesting* attribute were set on all
291+
tasklets.
292+
293+
``Py_WATCHDOG_TIMEOUT``
294+
Interprets *timeout* as a fixed run time, rather than a
295+
per-tasklet run limit. The function will then attempt to
296+
interrupt execution once this many total opcodes have
297+
been executed since the call was made.
298+
299+
debugging and monitoring functions
300+
----------------------------------
301+
302+
.. c:function:: int PyStackless_SetChannelCallback(PyObject *callable)
303+
304+
channel debugging. The callable will be called on every send or receive.
305+
Passing NULL removes the handler.
306+
Parameters of the callable:
307+
channel, tasklet, int sendflag, int willblock
308+
-1 = failure
309+
310+
.. c:function:: int PyStackless_SetScheduleCallback(PyObject *callable)
311+
312+
scheduler monitoring.
313+
The callable will be called on every scheduling.
314+
Passing NULL removes the handler.
315+
Parameters of the callable: from, to
316+
When a tasklet dies, to is None.
317+
After death or when main starts up, from is None.
318+
-1 = failure
319+
320+
.. c:function:: void PyStackless_SetScheduleFastcallback(slp_schedule_hook_func func)
321+
322+
Scheduler monitoring with a faster interface.
323+
324+
Interface functions
325+
-------------------
326+
327+
Most of the above functions can be called both from "inside"
328+
and "outside" stackless. "inside" means there should be a running
329+
(c)frame on top which acts as the "main tasklet". The functions
330+
do a check whether the main tasklet exists, and wrap themselves
331+
if it is necessary.
332+
The following routines are used to support this, and you may use
333+
them as well if you need to make your specific functions always
334+
available.
335+
336+
.. c:function:: PyObject *PyStackless_Call_Main(PyObject *func, PyObject *args, PyObject *kwds)
337+
338+
Run any callable as the "main" |PY| function. Returns a |PY| object, or
339+
*NULL* in the case of failure.
340+
341+
.. c:function:: PyObject *PyStackless_CallMethod_Main(PyObject *o, char *name, char *format, ...)
342+
343+
Convenience: Run any method as the "main" |PY| function. Wraps PyStackless_Call_Main.

0 commit comments

Comments
 (0)