static PyObject * channel_send_sequence(PyChannelObject *self, PyObject *v) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); /*unused: PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type;*/ PyObject *it; PyCFrameObject *f; if (!stackless) return _channel_send_sequence(self, v); it = PyObject_GetIter(v); if (it == NULL) return NULL; f = slp_cframe_new(channel_seq_callback, 1); if (f == NULL) goto error; f->ob1 = it; Py_INCREF(self); f->ob2 = (PyObject *) self; f->i = 0; f->n = 0; ts->frame = (PyFrameObject *) f; Py_INCREF(Py_None); return STACKLESS_PACK(Py_None); error: Py_DECREF(it); return NULL; }
static PyObject * channel_send_exception(PyObject *myself, PyObject *args) { STACKLESS_GETARG(); PyObject *retval = NULL; PyObject *klass = PySequence_GetItem(args, 0); if (klass == NULL) VALUE_ERROR("channel.send_exception(e, v...)", NULL); args = PySequence_GetSlice(args, 1, PySequence_Size(args)); if (!args) { goto err_exit; } STACKLESS_PROMOTE_ALL(); retval = impl_channel_send_exception((PyChannelObject*)myself, klass, args); STACKLESS_ASSERT(); if (retval == NULL || STACKLESS_UNWINDING(retval)) { goto err_exit; } Py_INCREF(Py_None); retval = Py_None; err_exit: Py_DECREF(klass); Py_XDECREF(args); return retval; }
static PyObject * wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds) { STACKLESS_GETARG(); wrapperfunc wrapper = wp->descr->d_base->wrapper; PyObject *self = wp->self; PyObject *ret; if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) { wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper; STACKLESS_PROMOTE_WRAPPER(wp); ret = (*wk)(self, args, wp->descr->d_wrapped, kwds); STACKLESS_ASSERT(); return ret; } if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) { PyErr_Format(PyExc_TypeError, "wrapper %s doesn't take keyword arguments", wp->descr->d_base->name); return NULL; } STACKLESS_PROMOTE_WRAPPER(wp); ret = (*wrapper)(self, args, wp->descr->d_wrapped); STACKLESS_ASSERT(); return ret; }
static TASKLET_KILL_HEAD(impl_tasklet_kill) { STACKLESS_GETARG(); PyObject *noargs; PyObject *ret; /* * silently do nothing if the tasklet is dead. * simple raising would kill ourself in this case. */ if (slp_get_frame(task) == NULL) Py_RETURN_NONE; /* we might be called after exceptions are gone */ if (PyExc_TaskletExit == NULL) { PyExc_TaskletExit = PyString_FromString("zombie"); if (PyExc_TaskletExit == NULL) return NULL; /* give up */ } noargs = PyTuple_New(0); STACKLESS_PROMOTE_ALL(); ret = impl_tasklet_raise_exception(task, PyExc_TaskletExit, noargs); STACKLESS_ASSERT(); Py_DECREF(noargs); return ret; }
static CHANNEL_SEND_HEAD(impl_channel_send) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); if(ts->st.main == NULL) return PyChannel_Send_M(self, arg); return generic_channel_action(self, arg, 1, stackless); }
static CHANNEL_RECEIVE_HEAD(impl_channel_receive) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); if (ts->st.main == NULL) return PyChannel_Receive_M(self); return generic_channel_action(self, Py_None, -1, stackless); }
static PyObject * impl_channel_send(PyChannelObject *self, PyObject *arg) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); if(ts->st.main == NULL) return PyChannel_Send_M(self, arg); return generic_channel_action(self, arg, 1, stackless); }
static PyObject * impl_channel_receive(PyChannelObject *self) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); if (ts->st.main == NULL) return PyChannel_Receive_M(self); return generic_channel_action(self, Py_None, -1, stackless); }
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); }
static PyObject * channel_iternext(PyChannelObject *self) { STACKLESS_GETARG(); if (self->flags.closing && self->balance == 0) { /* signal the end of the iteration */ return NULL; } STACKLESS_PROMOTE_ALL(); return impl_channel_receive(self); }
static PyObject * schedule_generic(PyObject *self, PyObject *args, PyObject *kwds, int remove) { STACKLESS_GETARG(); PyObject *retval = (PyObject *) PyThreadState_GET()->st.current; static char *argnames[] = {"retval", NULL}; if (PyTuple_GET_SIZE(args) > 0) { if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:schedule", argnames, &retval)) return NULL; } STACKLESS_PROMOTE_ALL(); return PyStackless_Schedule(retval, remove); }
static PyObject * run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals, PyCompilerFlags *flags, PyArena *arena) { STACKLESS_GETARG(); PyCodeObject *co; PyObject *v; co = PyAST_Compile(mod, filename, flags, arena); if (co == NULL) return NULL; STACKLESS_PROMOTE_ALL(); v = PyEval_EvalCode(co, globals, locals); STACKLESS_ASSERT(); Py_DECREF(co); return v; }
static PyObject * classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) { STACKLESS_GETARG(); PyObject *func, *result; func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type); if (func == NULL) return NULL; STACKLESS_PROMOTE_ALL(); result = PyEval_CallObjectWithKeywords(func, args, kwds); STACKLESS_ASSERT(); Py_DECREF(func); return result; }
static CHANNEL_SEND_EXCEPTION_HEAD(impl_channel_send_exception) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); PyObject *bomb, *ret = NULL; assert(PyChannel_Check(self)); if (ts->st.main == NULL) return PyChannel_SendException_M(self, klass, args); bomb = slp_make_bomb(klass, args, "channel.send_exception"); if (bomb != NULL) { ret = generic_channel_action(self, bomb, 1, stackless); Py_DECREF(bomb); } return ret; }
static PyObject * wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) { STACKLESS_GETARG(); Py_ssize_t argc; PyObject *self, *func, *result; /* Make sure that the first argument is acceptable as 'self' */ assert(PyTuple_Check(args)); argc = PyTuple_GET_SIZE(args); if (argc < 1) { PyErr_Format(PyExc_TypeError, "descriptor '%.300s' of '%.100s' " "object needs an argument", descr_name((PyDescrObject *)descr), descr->d_type->tp_name); return NULL; } self = PyTuple_GET_ITEM(args, 0); if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) { PyErr_Format(PyExc_TypeError, "descriptor '%.200s' " "requires a '%.100s' object " "but received a '%.100s'", descr_name((PyDescrObject *)descr), descr->d_type->tp_name, self->ob_type->tp_name); return NULL; } func = PyWrapper_New((PyObject *)descr, self); if (func == NULL) return NULL; args = PyTuple_GetSlice(args, 1, argc); if (args == NULL) { Py_DECREF(func); return NULL; } STACKLESS_PROMOTE_ALL(); result = PyEval_CallObjectWithKeywords(func, args, kwds); STACKLESS_ASSERT(); Py_DECREF(args); Py_DECREF(func); return result; }
static PyObject * impl_channel_send_throw(PyChannelObject *self, PyObject *exc, PyObject *val, PyObject *tb) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); PyObject *bomb, *ret = NULL; assert(PyChannel_Check(self)); if (ts->st.main == NULL) return PyChannel_SendThrow_M(self, exc, val, tb); bomb = slp_exc_to_bomb(exc, val, tb); if (bomb != NULL) { ret = generic_channel_action(self, bomb, 1, stackless); Py_DECREF(bomb); } return ret; }
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); }
PyObject * PyRun_StringFlags(const char *str, int start, PyObject *globals, PyObject *locals, PyCompilerFlags *flags) { STACKLESS_GETARG(); PyObject *ret = NULL; mod_ty mod; PyArena *arena = PyArena_New(); if (arena == NULL) return NULL; mod = PyParser_ASTFromString(str, "<string>", start, flags, arena); if (mod != NULL) { STACKLESS_PROMOTE_ALL(); ret = run_mod(mod, "<string>", globals, locals, flags, arena); } PyArena_Free(arena); return ret; }
PyObject * PyStackless_Schedule(PyObject *retval, int remove) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); PyTaskletObject *prev = ts->st.current, *next = prev->next; PyObject *ret = NULL; if (ts->st.main == NULL) return PyStackless_Schedule_M(retval, remove); Py_INCREF(prev); TASKLET_SETVAL(prev, retval); if (remove) { slp_current_remove(); Py_DECREF(prev); } ret = slp_schedule_task(prev, next, stackless); Py_DECREF(prev); return ret; }
static PyObject * tasklet_raise_exception(PyObject *myself, PyObject *args) { STACKLESS_GETARG(); PyObject *result = NULL; PyObject *klass = PySequence_GetItem(args, 0); if (klass == NULL) VALUE_ERROR("tasklet.raise_exception(e, v...)", NULL); args = PySequence_GetSlice(args, 1, PySequence_Size(args)); if (!args) goto err_exit; STACKLESS_PROMOTE_ALL(); result = impl_tasklet_raise_exception( (PyTaskletObject*)myself, klass, args); STACKLESS_ASSERT(); err_exit: Py_DECREF(klass); Py_XDECREF(args); return result; }
PyObject * PyStackless_Schedule(PyObject *retval, int remove) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); PyTaskletObject *prev = ts->st.current, *next = prev->next; PyObject *ret = NULL; int switched; if (ts->st.main == NULL) return PyStackless_Schedule_M(retval, remove); /* make sure we hold a reference to the previous tasklet */ Py_INCREF(prev); TASKLET_SETVAL(prev, retval); if (remove) { slp_current_remove(); Py_DECREF(prev); if (next == prev) next = 0; /* we were the last runnable tasklet */ } /* we mustn't DECREF prev here (after the slp_schedule_task(). * This could be the last reference, thus * promting emergency reactivation of the tasklet, * and soft switching isn't really done until we have unwound. * Use the delayed release mechanism instead. */ assert(ts->st.del_post_switch == NULL); ts->st.del_post_switch = (PyObject*)prev; ret = slp_schedule_task(prev, next, stackless, &switched); /* however, if this was a no-op (e.g. prev==next, or an error occurred) * we need to decref prev ourselves */ if (!switched) Py_CLEAR(ts->st.del_post_switch); return ret; }
static PyObject * channel_send_throw(PyObject *myself, PyObject *args) { STACKLESS_GETARG(); PyObject *typ; PyObject *tb = Py_None; PyObject *val = Py_None; PyObject *retval; if (!PyArg_UnpackTuple(args, "send_throw", 1, 3, &typ, &val, &tb)) return NULL; STACKLESS_PROMOTE_ALL(); retval = impl_channel_send_throw((PyChannelObject*)myself, typ, val, tb); STACKLESS_ASSERT(); if (retval == NULL || STACKLESS_UNWINDING(retval)) { goto err_exit; } Py_INCREF(Py_None); retval = Py_None; err_exit: return retval; }
PyObject * PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals, int closeit, PyCompilerFlags *flags) { STACKLESS_GETARG(); PyObject *ret; mod_ty mod; PyArena *arena = PyArena_New(); if (arena == NULL) return NULL; mod = PyParser_ASTFromFile(fp, filename, start, 0, 0, flags, NULL, arena); if (closeit) fclose(fp); if (mod == NULL) { PyArena_Free(arena); return NULL; } STACKLESS_PROMOTE_ALL(); ret = run_mod(mod, filename, globals, locals, flags, arena); PyArena_Free(arena); return ret; }
static PyObject * channel_send(PyObject *self, PyObject *arg) { STACKLESS_GETARG(); return generic_channel_action((PyChannelObject*)self, arg, 1, stackless); }
PyObject * PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { STACKLESS_GETARG(); PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); Py_ssize_t size; #ifdef STACKLESS switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS)) { #else switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { #endif case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) WRAP_RETURN( (*meth)(self, arg) ) break; case METH_VARARGS | METH_KEYWORDS: WRAP_RETURN( (*(PyCFunctionWithKeywords)meth)(self, arg, kw) ) case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 0) WRAP_RETURN( (*meth)(self, NULL) ) PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); return NULL; } break; case METH_O: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) WRAP_RETURN( (*meth)(self, PyTuple_GET_ITEM(arg, 0)) ) PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); return NULL; } break; default: PyErr_SetString(PyExc_SystemError, "Bad call flags in " "PyCFunction_Call. METH_OLDARGS is no " "longer supported!"); return NULL; } PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; } /* Methods (the standard built-in methods, that is) */ static void meth_dealloc(PyCFunctionObject *m) { _PyObject_GC_UNTRACK(m); Py_XDECREF(m->m_self); Py_XDECREF(m->m_module); if (numfree < PyCFunction_MAXFREELIST) { m->m_self = (PyObject *)free_list; free_list = m; numfree++; } else { PyObject_GC_Del(m); } }
PyObject * PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { STACKLESS_GETARG(); PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); Py_ssize_t size; #ifdef STACKLESS switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS)) { #else switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { #endif case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) WRAP_RETURN( (*meth)(self, arg) ) break; case METH_VARARGS | METH_KEYWORDS: case METH_OLDARGS | METH_KEYWORDS: WRAP_RETURN( (*(PyCFunctionWithKeywords)meth)(self, arg, kw) ) case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 0) WRAP_RETURN( (*meth)(self, NULL) ) PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); return NULL; } break; case METH_O: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) WRAP_RETURN( (*meth)(self, PyTuple_GET_ITEM(arg, 0)) ) PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); return NULL; } break; case METH_OLDARGS: /* the really old style */ if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) arg = PyTuple_GET_ITEM(arg, 0); else if (size == 0) arg = NULL; WRAP_RETURN( (*meth)(self, arg) ) } break; default: PyErr_BadInternalCall(); return NULL; } PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; }