3
3
|SLP | C-API
4
4
===========
5
5
6
+ .. note ::
7
+
8
+ Some switching functions have a variant with the
9
+ same name, but ending on "_nr". These are non-recursive
10
+ versions with the same functionality, but they might
11
+ avoid a hard stack switch.
12
+ Their return value is ternary, and they require the
13
+ caller to return to its frame, properly.
14
+ All three different cases must be treated.
15
+
16
+ Ternary return from an integer function:
17
+
18
+ ===== ============= ===============================
19
+ value meaning action
20
+ ===== ============= ===============================
21
+ -1 failure return NULL
22
+ 1 soft switched return :c:data: `Py_UnwindToken `
23
+ 0 hard switched return :c:data: `Py_None `
24
+ ===== ============= ===============================
25
+
26
+ Ternary return from a PyObject * function:
27
+
28
+ ============== ============= ===============================
29
+ value meaning action
30
+ ============== ============= ===============================
31
+ NULL failure return NULL
32
+ Py_UnwindToken soft switched return :c:data: `Py_UnwindToken `
33
+ other hard switched return value
34
+ ============== ============= ===============================
35
+
36
+
6
37
|SLP | provides the following C functions.
7
38
8
39
Tasklets
@@ -262,8 +293,8 @@ Channels
262
293
263
294
Gets the balance for *self *. See :attr: `channel.balance `.
264
295
265
- stackless module
266
- ----------------
296
+ Module :py:mod: ` stackless `
297
+ --------------------------
267
298
268
299
.. c :function :: PyObject *PyStackless_Schedule (PyObject *retval, int remove)
269
300
@@ -354,7 +385,8 @@ Soft-switchable extension functions
354
385
355
386
A soft switchable extension function or method is a function or method defined
356
387
by an extension module written in C. In contrast to an normal C-function you
357
- can soft-switch tasklets while this function executes. At the C-language level
388
+ can soft-switch tasklets while this function executes. Soft-switchable functions
389
+ obey the stackless-protocol. At the C-language level
358
390
such a function or method is made from 3 C-definitions:
359
391
360
392
1. A declaration object of type :c:type:`PyStacklessFunctionDeclaration_Type`.
@@ -378,10 +410,10 @@ Typedef ``slp_softswitchablefunc``::
378
410
379
411
.. c :type :: PyStacklessFunctionDeclarationObject
380
412
381
- This subtype of :c:type: `PyObject ` represents a Stackless soft switchable
382
- extension function declaration object.
413
+ This subtype of :c:type: `PyObject ` represents a Stackless soft switchable
414
+ extension function declaration object.
383
415
384
- Here is the structure definition::
416
+ Here is the structure definition::
385
417
386
418
typedef struct {
387
419
PyObject_HEAD
@@ -390,42 +422,142 @@ Typedef ``slp_softswitchablefunc``::
390
422
const char * module_name;
391
423
} PyStacklessFunctionDeclarationObject;
392
424
393
- .. c :member :: slp_softswitchablefunc PyStacklessFunctionDeclarationObject.sfunc
425
+ .. c :member :: slp_softswitchablefunc PyStacklessFunctionDeclarationObject.sfunc
394
426
395
- Pointer to implementation function.
427
+ Pointer to implementation function.
396
428
397
- .. c :member :: const char * PyStacklessFunctionDeclarationObject.name
429
+ .. c :member :: const char * PyStacklessFunctionDeclarationObject.name
398
430
399
- Name of the function.
431
+ Name of the function.
400
432
401
- .. c :member :: const char * PyStacklessFunctionDeclarationObject.module_name
433
+ .. c :member :: const char * PyStacklessFunctionDeclarationObject.module_name
402
434
403
- Name of the containing module.
435
+ Name of the containing module.
404
436
405
437
.. c :var :: PyTypeObject PyStacklessFunctionDeclaration_Type
406
438
407
- This instance of :c:type: `PyTypeObject ` represents the Stackless
408
- soft switchable extension function declaration type.
439
+ This instance of :c:type: `PyTypeObject ` represents the Stackless
440
+ soft switchable extension function declaration type.
409
441
410
442
.. c :function :: int PyStacklessFunctionDeclarationType_CheckExact (PyObject *p)
411
443
412
- Return true if *p * is a PyStacklessFunctionDeclarationObject object, but
413
- not an instance of a subtype of this type.
444
+ Return true if *p * is a PyStacklessFunctionDeclarationObject object, but
445
+ not an instance of a subtype of this type.
414
446
415
447
.. c :function :: PyObject* PyStackless_CallFunction (PyStacklessFunctionDeclarationObject *sfd, PyObject *arg, PyObject *ob1, PyObject *ob2, PyObject *ob3, long n, void *any)
416
448
417
- Invoke the soft switchable extension, which is represented by *sfd *.
418
- Pass *arg * as initial value for argument *retval * and *ob1 *, *ob2 *, *ob3 *,
419
- *n * and *any * as general purpose in-out-arguments.
449
+ Invoke the soft switchable extension, which is represented by *sfd *.
450
+ Pass *arg * as initial value for argument *retval * and *ob1 *, *ob2 *, *ob3 *,
451
+ *n * and *any * as general purpose in-out-arguments.
420
452
421
- Return the result of the function call or :c:data: `Py_UnwindToken `.
453
+ Return the result of the function call or :c:data: `Py_UnwindToken `.
422
454
423
455
.. c :function :: int PyStackless_InitFunctionDeclaration (PyStacklessFunctionDeclarationObject *sfd, PyObject *module, PyModuleDef *module_def)
424
456
425
- Initialize the fields :c:member: `PyStacklessFunctionDeclarationObject.name ` and
426
- :c:member: `PyStacklessFunctionDeclarationObject.module_name ` of *sfd *.
457
+ Initialize the fields :c:member: `PyStacklessFunctionDeclarationObject.name ` and
458
+ :c:member: `PyStacklessFunctionDeclarationObject.module_name ` of *sfd *.
459
+
460
+ Within the body of a soft switchable extension function (or any other C-function, that obyes the stackless-protocol)
461
+ you need the following macros.
462
+
463
+ Macros for the "stackless-protocol"
464
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
465
+
466
+ How to does Stackless Python decide, if a function may return an unwind-token?
467
+ There is one global variable "_PyStackless_TRY_STACKLESS"[#]_ which is used
468
+ like an implicit parameter. Since we don't have a real parameter,
469
+ the flag is copied into the local variable "stackless" and cleared.
470
+ This is done by the STACKLESS_GETARG() macro, which should be added to
471
+ the top of the function's declarations.
472
+
473
+ The idea is to keep the chances to introduce error to the minimum.
474
+ A function can safely do some tests and return before calling
475
+ anything, since the flag is in a local variable.
476
+ Depending on context, this flag is propagated to other called
477
+ functions. They *must * obey the protocol. To make this sure,
478
+ the STACKLESS_ASSERT() macro has to be called after every such call.
479
+
480
+ Many internal functions have been patched to support this protocol.
481
+ Their first action is a direct or indirect call of the macro
482
+ :c:func: `STACKLESS_GETARG `.
483
+
484
+ .. c :function :: STACKLESS_GETARG()
485
+
486
+ Define the local variable ``int stackless `` and move the global
487
+ "_PyStackless_TRY_STACKLESS" flag into the local variable "stackless".
488
+ After a call to :c:func: `STACKLESS_GETARG ` the value of
489
+ "_PyStackless_TRY_STACKLESS" is 0.
490
+
491
+ .. c :function :: STACKLESS_PROMOTE_ALL()
492
+
493
+ All STACKLESS_PROMOTE_xxx macros are used to propagate the stackless-flag
494
+ from the local variable "stackless" to the global variable
495
+ "_PyStackless_TRY_STACKLESS". The macro :c:func: `STACKLESS_PROMOTE_ALL ` does
496
+ this unconditionally. It is used for cases where we know that the called
497
+ function will take care of our object, and we need no test. For example,
498
+ :c:func: `PyObject_Call ` and all other Py{Object,Function,CFunction}_*Call*
499
+ functions use STACKLESS_PROMOTE_xxx itself, so we don't need to check further.
500
+
501
+ .. c :function :: STACKLESS_PROMOTE_FLAG(flag)
427
502
428
- debugging and monitoring functions
503
+ This macro is the most general conditional variant.
504
+ If the local variable "stackless" was set, it sets the global
505
+ variable "_PyStackless_TRY_STACKLESS" to *flag * and returns *flag *.
506
+ Otherwise the macro returns 0. It is used for special cases,
507
+ like PyCFunction objects. PyCFunction_Type
508
+ says that it supports a stackless call, but the final action depends
509
+ on the METH_STACKLESS flag in the object to be called. Therefore,
510
+ PyCFunction_Call uses ``STACKLESS_PROMOTE_FLAG(flags & METH_STACKLESS) `` to
511
+ take care of PyCFunctions which don't care about it.
512
+
513
+ Another example is the "next" method of iterators. To support this,
514
+ the wrapperobject's type has the Py_TPFLAGS_HAVE_STACKLESS_CALL
515
+ flag set, but wrapper_call then examines the wrapper descriptors
516
+ flags if PyWrapperFlag_STACKLESS is set. "next" has it set.
517
+ It also checks whether Py_TPFLAGS_HAVE_STACKLESS_CALL is set
518
+ for the iterator's type.
519
+
520
+ .. c :function :: STACKLESS_PROMOTE_METHOD(obj, slot_name)
521
+
522
+ If the local variable "stackless" was set and if the type method for the
523
+ slot *slot_name * of the type of object *obj * obeys the stackless-protocol,
524
+ then _PyStackless_TRY_STACKLESS is set to 1, and we
525
+ expect that the function handles it correctly.
526
+
527
+ .. c :function :: STACKLESS_PROMOTE(obj)
528
+
529
+ A special optimized variant of ``STACKLESS_PROMOTE_METHOD( `` *obj * ``, tp_call) ``.
530
+
531
+ .. c :function :: STACKLESS_ASSERT()
532
+
533
+ In debug builds this macro asserts that _PyStackless_TRY_STACKLESS was cleared.
534
+ This debug feature tries to ensure that no unexpected nonrecursive call can happen.
535
+ In release builds this macro does nothing.
536
+
537
+ .. c :function :: STACKLESS_RETRACT()
538
+
539
+ Set the global variable "_PyStackless_TRY_STACKLESS" unconditionally to 0.
540
+ Rarely used.
541
+
542
+ Examples
543
+ ~~~~~~~~
544
+
545
+ The Stackless test-module :py:mod: `_teststackless ` contains the following
546
+ example for a soft switchable function.
547
+ To call it use
548
+ ``PyStackless_CallFunction(&demo_soft_switchable_declaration, result, NULL, NULL, NULL, action, NULL) ``.
549
+
550
+ .. include :: ../../Stackless/module/_teststackless.c
551
+ :code: c
552
+ :encoding: utf-8
553
+ :start-after: /*DO-NOT-REMOVE-OR-MODIFY-THIS-MARKER:ssf-example-start */
554
+ :end-before: /*DO-NOT-REMOVE-OR-MODIFY-THIS-MARKER:ssf-example-end */
555
+
556
+
557
+ .. [# ] Actually "_PyStackless_TRY_STACKLESS" is a macro that expands to a C L-value. As long as
558
+ |CPY | uses the GIL, this L-value is a global variable.
559
+
560
+ Debugging and monitoring Functions
429
561
----------------------------------
430
562
431
563
.. c :function :: int PyStackless_SetChannelCallback (PyObject *callable)
@@ -460,6 +592,12 @@ Stack unwinding
460
592
461
593
A singleton that indicates C-stack unwinding
462
594
595
+ .. note::
596
+
597
+ :c:data:`Py_UnwindToken` is *never* inc/decref'ed. Use the
598
+ macro :c:func:`STACKLESS_UNWINDING` to test for
599
+ Py_UnwindToken.
600
+
463
601
.. c:function:: int STACKLESS_UNWINDING(obj)
464
602
465
603
Return 1, if *obj* is :c:data:`Py_UnwindToken` and 0 otherwise.
0 commit comments