static TASKLET_RAISE_EXCEPTION_HEAD(impl_tasklet_raise_exception) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); PyObject *bomb; if (ts->st.main == NULL) return PyTasklet_RaiseException_M(self, klass, args); bomb = slp_make_bomb(klass, args, "tasklet.raise_exception"); if (bomb == NULL) return NULL; TASKLET_SETVAL_OWN(self, bomb); /* if the tasklet is dead, do not run it (no frame) but explode */ if (slp_get_frame(self) == NULL) { TASKLET_CLAIMVAL(self, &bomb); return slp_bomb_explode(bomb); } return slp_schedule_task(ts->st.current, self, stackless, 0); }
static PyObject * generic_channel_action(PyChannelObject *self, PyObject *arg, int dir, int stackless) { PyThreadState *ts = PyThreadState_GET(); PyTaskletObject *source = ts->st.current; PyTaskletObject *target = self->head; int cando = dir > 0 ? self->balance < 0 : self->balance > 0; int interthread = cando ? target->cstate->tstate != ts : 0; PyObject *tmpval, *retval; int fail; assert(abs(dir) == 1); /* set the channel tmpval here, for the callback */ TASKLET_CLAIMVAL(source, &tmpval); TASKLET_SETVAL(source, arg); /* note that notify might release the GIL. */ /* XXX for the moment, we notify late on interthread */ if (!interthread) NOTIFY_CHANNEL(self, source, dir, cando, NULL); if (cando) /* communication 1): there is somebody waiting */ fail = generic_channel_cando(ts, &retval, self, dir, stackless); else fail = generic_channel_block(ts, &retval, self, dir, stackless); if (fail) { TASKLET_SETVAL_OWN(source, tmpval); return NULL; } Py_DECREF(tmpval); if (interthread) NOTIFY_CHANNEL(self, source, dir, cando, NULL); return retval; }