Stackless-Python C-API¶
Stackless-Python provides the following C functions.
Tasklets¶
- PyTaskletObject *
PyTasklet_New(PyTypeObject *type,PyObject *func)¶ Return a new tasklet object.type must be derived from
PyTasklet_TypeorNULL.func must be a callable object orNULLorPy_None. IffuncisNULLorPy_Noneyou must set it later withPyTasklet_BindEx().
- int
PyTasklet_Setup(PyTaskletObject *task,PyObject *args,PyObject *kwds)¶ Binds a tasklet function to parameters, making it ready to run and inserts ininto the runnables queue. Returns
0if successful or-1in the case of failure.
- int
PyTasklet_BindEx(PyTaskletObject *task,PyObject *func,PyObject *args,PyObject *kwargs)¶ Binds a tasklet to a function and/or to parameters, making it ready to run. This is the C equivalent tomethod
tasklet.bind(). The argumentsfunc,args andkwargs are optional andmay beNULLorPy_None. Returns0if successful or-1in the case of failure.
- int
PyTasklet_BindThread(PyTaskletObject *task, long thread_id)¶ Binds a tasklet function to a thread. This is the C equivalent tomethod
tasklet.bind_thread(). Returns0if successful or-1in the case of failure.
- int
PyTasklet_Run(PyTaskletObject *task)¶ Forcestask to run immediately. Returns
0if successful, and-1in thecase of failure.
- int
PyTasklet_Run_nr(PyTaskletObject *task)¶ Forcestask to run immediately, soft switching if possible. Returns
1ifthe call soft switched,0if the call hard switched and -1 in the case offailure.
- int
PyTasklet_Switch(PyTaskletObject *task)¶ Forcestask to run immediately. The previous tasklet is paused.Returns
0if successful, and-1in thecase of failure.
- int
PyTasklet_Switch_nr(PyTaskletObject *task)¶ Forcestask to run immediately, soft switching if possible.The previous tasklet is paused. Returns
1ifthe call soft switched,0if the call hard switched and -1 in the case offailure.
- int
PyTasklet_Remove(PyTaskletObject *task)¶ Removestask from the runnables queue. Be careful! If this tasklet has a Cstack attached, you need to either resume running it or kill it. Just droppingit might give an inconsistent system state. Returns
0if successful, and-1in the case of failure.
- int
PyTasklet_Insert(PyTaskletObject *task)¶ Inserttask into the runnables queue, if it isn’t already there. If it isblocked or dead, the function returns
-1and aRuntimeErroris raised.
- int
PyTasklet_RaiseException(PyTaskletObject *self,PyObject *klass,PyObject *args)¶ Raises an instance of theklass exception on theself tasklet.klass mustbe a subclass of
Exception. Returns1if the call soft switched,0if the call hard switched and-1in the case of failure.Note
Raising
TaskletExiton a tasklet can be done to silently killit, seePyTasklet_Kill().
- int
PyTasklet_Throw(PyTaskletObject *self, int pending,PyObject *exc,PyObject *val,PyObject *tb)¶ Raises (exc,val,tb) on theself tasklet. This is the C equivalent tomethod
tasklet.throw(). Returns1if the call soft switched,0if the call hard switched and-1in the case of failure.
- int
PyTasklet_Kill(PyTaskletObject *self)¶ Raises
TaskletExiton taskletself. This should result intask beingsilently killed. (This exception is ignored by tasklet_end anddoes not invoke main as exception handler.)Returns1if the call soft switched,0if the call hardswitched and-1in the case of failure.
- int
PyTasklet_KillEx(PyTaskletObject *self, int pending)¶ Raises
TaskletExiton taskletself. This is the C equivalent tomethodtasklet.kill().Returns1if the call soft switched,0if the call hardswitched and-1in the case of failure.
- int
PyTasklet_GetAtomic(PyTaskletObject *task)¶ Returns
1iftask is atomic, otherwise0.
- int
PyTasklet_SetAtomic(PyTaskletObject *task, int flag)¶ Returns
1iftask is currently atomic, otherwise0. Sets theatomic attribute to the logical value offlag.
- int
PyTasklet_GetIgnoreNesting(PyTaskletObject *task)¶ Returns
1iftask ignores its nesting level when choosing whether toauto-schedule it, otherwise0.
- int
PyTasklet_SetIgnoreNesting(PyTaskletObject *task, int flag)¶ Returns the existing value of theignore_nesting attribute for the tasklettask, setting it to the logical value offlag. If true, the tasklet maybe auto-scheduled even if itsnesting_level is >
0.
- int
PyTasklet_GetBlockTrap(PyTaskletObject *task)¶ Returns
1iftask is designated as not being allowed to be blocked on achannel, otherwise0.
- void
PyTasklet_SetBlockTrap(PyTaskletObject *task, int value)¶ Returns
1iftask was already designated as not being allowed to be blockedon a channel, otherwise0. This attribute is set to the logical value ofvalue.
- PyObject *
PyTasklet_GetFrame(PyTaskletObject *task)¶ Returns the current frame thattask is executing in, orNULL
- int
PyTasklet_IsMain(PyTaskletObject *task)¶ Returns
1iftask is the main tasklet, otherwise0.
- int
PyTasklet_IsCurrent(PyTaskletObject *task)¶ Returns
1iftask is the current tasklet, otherwise0.
- int
PyTasklet_GetRecursionDepth(PyTaskletObject *task)¶ Return the current recursion depth oftask.
- int
PyTasklet_GetNestingLevel(PyTaskletObject *task)¶ Return the current nesting level oftask.
- int
PyTasklet_Alive(PyTaskletObject *task)¶ Returns
1iftask is alive (has an associated frame), otherwise0if it is dead.
- int
PyTasklet_Paused(PyTaskletObject *task)¶ Returns
1iftask is paused, otherwise0. A tasklet is paused if it isalive, but not scheduled or blocked on a channel.
- int
PyTasklet_Scheduled(PyTaskletObject *task)¶ Returns
1iftask is scheduled, otherwise0. In the context of thisfunction a tasklet is considered to be scheduled if it is alive, and in thescheduler runnables list or blocked on a channel.
- int
PyTasklet_Restorable(PyTaskletObject *task)¶ Returns
1iftask can be fully unpickled, otherwise0. A tasklet canbe pickled whether it is fully restorable or not for the purposes of debuggingand introspection. A tasklet that has been hard-switched cannot be fullypickled, for instance.
Channels¶
- PyChannelObject*
PyChannel_New(PyTypeObject *type)¶ Return a new channel object, orNULL in the case of failure.type must bederived from
PyChannel_Typeor beNULL, otherwise aTypeErroris raised.
- int
PyChannel_Send(PyChannelObject *self,PyObject *arg)¶ Sendarg on the channelself. Returns
0if the operation wassuccessful, or-1in the case of failure.
- int
PyChannel_Send_nr(PyChannelObject *self,PyObject *arg)¶ Sendarg on the channelself, soft switching if possible. Returns
1ifthe call soft switched,0if the call hard switched and -1 in the case offailure.
- PyObject *
PyChannel_Receive(PyChannelObject *self)¶ Receive on the channelself. Returns aPython® object if the operation wassuccessful, orNULL in the case of failure.
- PyObject *
PyChannel_Receive_nr(PyChannelObject *self)¶ Receive on the channelself, soft switching if possible. Returns aPython®object if the operation was successful,
Py_UnwindTokenif a soft switchoccurred, orNULL in the case of failure.
- int
PyChannel_SendException(PyChannelObject *self,PyObject *klass,PyObject *value)¶ Returns
0if successful or-1in the case of failure. An instance of theexception typeklass is raised on the first tasklet blocked on channelself.
- int
PyChannel_SendThrow(PyChannelObject *self,PyObject *exc,PyObject *val,PyObject *tb)¶ Returns
0if successful or-1in the case of failure.(exc,val,tb) is raised on the first tasklet blocked on channelself.
- PyObject *
PyChannel_GetQueue(PyChannelObject *self)¶ Returns the first tasklet in the channelself’s queue, orNULL in the casethe queue is empty.
- void
PyChannel_Close(PyChannelObject *self)¶ Marks the channelself as closing. No further tasklets can be blocked on theit from this point, unless it is later reopened.
- void
PyChannel_Open(PyChannelObject *self)¶ Reopens the channelself. This allows tasklets to once again send and receiveon it, if those operations would otherwise block the given tasklet.
- int
PyChannel_GetClosing(PyChannelObject *self)¶ Returns
1if the channelself is marked as closing, otherwise0.
- int
PyChannel_GetClosed(PyChannelObject *self)¶ Returns
1if the channelself is marked as closing and there are no taskletsblocked on it, otherwise0.
- int
PyChannel_GetPreference(PyChannelObject *self)¶ Returns the current scheduling preference value ofself. See
channel.preference.
- void
PyChannel_SetPreference(PyChannelObject *self, int val)¶ Sets the current scheduling preference value ofself. See
channel.preference.
- int
PyChannel_GetScheduleAll(PyChannelObject *self)¶ Gets theschedule_all override flag forself. See
channel.schedule_all.
- void
PyChannel_SetScheduleAll(PyChannelObject *self, int val)¶ Sets theschedule_all override flag forself. See
channel.schedule_all.
- int
PyChannel_GetBalance(PyChannelObject *self)¶ Gets the balance forself. See
channel.balance.
stackless module¶
- PyObject *
PyStackless_Schedule(PyObject *retval, int remove)¶ Suspend the current tasklet and schedule the next one in the cyclic chain.if remove is nonzero, the current tasklet will be removed from the chain.retval = success NULL = failure
- PyObject *
PyStackless_Schedule_nr(PyObject *retval, int remove)¶ retval = success NULL = failureretval == Py_UnwindToken: soft switched
- int
PyStackless_GetRunCount()¶ get the number of runnable tasks of the current thread, including the current one.-1 = failure
- long
PyStackless_GetCurrentId()¶ Get a unique integer ID for the current tasklet
Threadsafe.
This is useful for benchmarking code thatneeds to get some sort of a stack identifier and mustnot worry about the GIL being present and so on.
Note
- the “main” tasklet on each thread will have the same id,even if a proper tasklet has not been initialized.
- IDs may get recycled for new tasklets.
- PyObject *
PyStackless_RunWatchdog(long timeout)¶ Runs the scheduler until there are no tasklets remaining within it, or untilone of the scheduled tasklets runs fortimeout VM instructions withoutblocking. ReturnsNone if the scheduler is empty, a tasklet object if thattasklet timed out, orNULL in the case of failure. If a timed out taskletis returned, it should be killed or reinserted.
This function can only be called from the main tasklet.During the run, main is suspended, but will be invokedafter the action. You will write your exception handlerhere, since every uncaught exception will be directedto main.
- PyObject *
PyStackless_RunWatchdogEx(long timeout, int flags)¶ Wraps
PyStackless_RunWatchdog(), but allows its behaviour to becustomised by the value offlags which may contain any of the followingbits:Py_WATCHDOG_THREADBLOCK- Allows a thread to block if it runs out of tasklets. Ideallyit will be awakened by other threads using channels which itsblocked tasklets are waiting on.
Py_WATCHDOG_SOFT- Instead of interrupting a tasklet, we wait until thenext tasklet scheduling moment to return. Always returnsPy_None, as everything is in order.
Py_WATCHDOG_IGNORE_NESTING- Allows interrupts at all levels, effectively acting asthough theignore_nesting attribute were set on alltasklets.
Py_WATCHDOG_TIMEOUT- Interpretstimeout as a fixed run time, rather than aper-tasklet run limit. The function will then attempt tointerrupt execution once this many total opcodes havebeen executed since the call was made.
debugging and monitoring functions¶
- int
PyStackless_SetChannelCallback(PyObject *callable)¶ channel debugging. The callable will be called on every send or receive.Passing NULL removes the handler.Parameters of the callable:channel, tasklet, int sendflag, int willblock-1 = failure
- int
PyStackless_SetScheduleCallback(PyObject *callable)¶ scheduler monitoring.The callable will be called on every scheduling.Passing NULL removes the handler.Parameters of the callable: from, toWhen a tasklet dies, to is None.After death or when main starts up, from is None.-1 = failure
- void
PyStackless_SetScheduleFastcallback(slp_schedule_hook_func func)¶ Scheduler monitoring with a faster interface.
Interface functions¶
Most of the above functions can be called both from “inside”and “outside” stackless. “inside” means there should be a running(c)frame on top which acts as the “main tasklet”. The functionsdo a check whether the main tasklet exists, and wrap themselvesif it is necessary.The following routines are used to support this, and you may usethem as well if you need to make your specific functions alwaysavailable.
