/* the special case to remove a specific tasklet */ PyTaskletObject * slp_channel_remove(PyChannelObject *channel, PyTaskletObject *task, int *dir_out, PyTaskletObject **next) { /* note: we assume that the task is in the channel! */ int dir = channel->balance > 0 ? 1 : -1; assert(channel->balance); if (task) { assert(PyTasklet_Check(task)); assert(slp_channel_has_tasklet(channel, task)); } else { task = channel->head; assert(PyTasklet_Check(task)); } if (dir_out) *dir_out = dir; if (next) *next = task->next; channel->balance -= dir; SLP_HEADCHAIN_REMOVE(task, next, prev); task->flags.blocked = 0; return task; }
static int impl_tasklet_setup(PyTaskletObject *task, PyObject *args, PyObject *kwds) { PyThreadState *ts = PyThreadState_GET(); PyFrameObject *frame; PyObject *func; assert(PyTasklet_Check(task)); if (ts->st.main == NULL) return PyTasklet_Setup_M(task, args, kwds); func = task->tempval; if (func == NULL) RUNTIME_ERROR("the tasklet was not bound to a function", -1); if ((frame = (PyFrameObject *) slp_cframe_newfunc(func, args, kwds, 0)) == NULL) { return -1; } if (bind_tasklet_to_frame(task, frame)) { Py_DECREF(frame); return -1; } TASKLET_SETVAL(task, Py_None); Py_INCREF(task); slp_current_insert(task); return 0; }
static PyObject * channel_setstate(PyObject *self, PyObject *args) { PyChannelObject *ch = (PyChannelObject *) self; PyTaskletObject *t; PyObject *lis; int flags, balance; int dir; Py_ssize_t i, n; if (!PyArg_ParseTuple(args, "iiO!:channel", &balance, &flags, &PyList_Type, &lis)) return NULL; channel_clear((PyObject *) ch); n = PyList_GET_SIZE(lis); *(int *)&ch->flags = flags; dir = balance > 0 ? 1 : -1; for (i = 0; i < n; i++) { t = (PyTaskletObject *) PyList_GET_ITEM(lis, i); if (PyTasklet_Check(t) && !t->flags.blocked) { Py_INCREF(t); slp_channel_insert(ch, t, dir); } } Py_INCREF(self); return self; }
static PyObject * tasklet_get_prev(PyTaskletObject *task) { PyObject *ret = Py_None; if (task->prev != NULL && PyTasklet_Check(task->prev)) ret = (PyObject *) task->prev; Py_INCREF(ret); return ret; }
static PyObject * tasklet_get_next(PyTaskletObject *task) { PyObject *ret = Py_None; if (task->next != NULL && PyTasklet_Check(task->next)) ret = (PyObject *) task->next; Py_INCREF(ret); return ret; }
static TASKLET_RUN_HEAD(impl_tasklet_run) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); assert(PyTasklet_Check(task)); if (ts->st.main == NULL) return PyTasklet_Run_M(task); if (PyTasklet_Insert(task)) return NULL; return slp_schedule_task(ts->st.current, task, stackless, 0); }
PyTaskletObject * slp_channel_remove_specific(PyChannelObject *channel, int dir, PyTaskletObject *task) { /* note: we assume that the task is in the channel! */ assert(PyTasklet_Check(task)); channel->balance -= dir; SLP_HEADCHAIN_REMOVE(task, next, prev); task->flags.blocked = 0; return task; }
PyTaskletObject * slp_channel_remove(PyChannelObject *channel, int dir) { PyTaskletObject *ret = channel->head; assert(PyTasklet_Check(ret)); channel->balance -= dir; SLP_HEADCHAIN_REMOVE(ret, next, prev); ret->flags.blocked = 0; return ret; };
/* see if a tasklet is queued on a channel */ #ifndef NDEBUG /* currently used only by assert */ static int slp_channel_has_tasklet(PyChannelObject *channel, PyTaskletObject *task) { PyTaskletObject *t = channel->head; while(PyTasklet_Check(t)) { if (t == task) return 1; t = t->next; } return 0; }
static TASKLET_INSERT_HEAD(impl_tasklet_insert) { PyThreadState *ts = PyThreadState_GET(); assert(PyTasklet_Check(task)); if (ts->st.main == NULL) return slp_current_wrapper(PyTasklet_Insert, task); if (task->flags.blocked) RUNTIME_ERROR("You cannot run a blocked tasklet", -1); if (task->f.frame == NULL && task != ts->st.current) RUNTIME_ERROR("You cannot run an unbound(dead) tasklet", -1); if (task->next == NULL) { Py_INCREF(task); slp_current_insert(task); /* The tasklet may belong to a different thread, and that thread may * be blocked, waiting for something to do! */ slp_thread_unblock(task->cstate->tstate); } return 0; }
static TASKLET_REMOVE_HEAD(impl_tasklet_remove) { PyThreadState *ts = PyThreadState_GET(); PyTaskletObject *hold = ts->st.current; assert(PyTasklet_Check(task)); if (ts->st.main == NULL) return PyTasklet_Remove_M(task); assert(ts->st.current != NULL); if (task->flags.blocked) RUNTIME_ERROR("You cannot remove a blocked tasklet.", -1); if (task == ts->st.current) RUNTIME_ERROR("The current tasklet cannot be removed.", -1); if (task->next == NULL) return 0; ts->st.current = task; slp_current_remove(); ts->st.current = hold; Py_DECREF(task); return 0; }