From tismer at centera.de Sun Mar 14 19:41:30 2004 From: tismer at centera.de (Christian Tismer) Date: Sun, 14 Mar 2004 19:41:30 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/sprint/Stackless stackless_tstate.h, 1.43, 1.44 stacklessmodule.c, 1.150, 1.151 taskletobject.c, 1.91, 1.92 Message-ID: Update of /home/cvs/slpdev/src/2.3/sprint/Stackless In directory centera.de:/tmp/cvs-serv17174 Modified Files: stackless_tstate.h stacklessmodule.c taskletobject.c Log Message: introduced pending_irg flag. In case an interrupt is not triggered due to the atomic flag, this flag is set instead. Then atmic is cleared by the setatomic method, the timeout is set to zero, to make sure that the event is triggered ASAP. Also introduced wants_value, needs more work. Index: stackless_tstate.h =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/stackless_tstate.h,v retrieving revision 1.43 retrieving revision 1.44 diff -C2 -d -r1.43 -r1.44 *** stackless_tstate.h 14 Mar 2004 14:20:06 -0000 1.43 --- stackless_tstate.h 14 Mar 2004 18:41:28 -0000 1.44 *************** *** 6,9 **** --- 6,11 ---- unsigned int block_trap: 1; unsigned int is_zombie: 1; + unsigned int wants_value: 1; + unsigned int pending_irq: 1; } PyTaskletFlagStruc; Index: stacklessmodule.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/stacklessmodule.c,v retrieving revision 1.150 retrieving revision 1.151 diff -C2 -d -r1.150 -r1.151 *** stacklessmodule.c 14 Mar 2004 14:20:06 -0000 1.150 --- stacklessmodule.c 14 Mar 2004 18:41:28 -0000 1.151 *************** *** 217,225 **** /* Tasklet has to be prevented from returning if atomic */ ! if (slp_get_flags(ts->st.current)->atomic > 0) { ts->st.ticker = ts->st.interval; Py_INCREF(Py_None); return Py_None; } Py_INCREF(ts->st.main); --- 217,228 ---- /* Tasklet has to be prevented from returning if atomic */ ! if (ts->st.flags.atomic) { ts->st.ticker = ts->st.interval; + ts->st.flags.pending_irq = 1; Py_INCREF(Py_None); return Py_None; } + else + ts->st.flags.pending_irq = 0; Py_INCREF(ts->st.main); Index: taskletobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/taskletobject.c,v retrieving revision 1.91 retrieving revision 1.92 diff -C2 -d -r1.91 -r1.92 *** taskletobject.c 14 Mar 2004 13:54:47 -0000 1.91 --- taskletobject.c 14 Mar 2004 18:41:28 -0000 1.92 *************** *** 619,622 **** --- 619,630 ---- ret = flags->atomic; flags->atomic = flag ? 1 : 0; + if (!flag && flags->pending_irq) { + /* trigger interrupt */ + PyThreadState *ts = PyThreadState_GET(); + if (_Py_Ticker > 0) + _Py_Ticker = 0; + ts->st.ticker = 0; + flags->pending_irq = 0; + } return ret; } _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From bob at centera.de Sat Mar 13 16:38:15 2004 From: bob at centera.de (Bob Ippolito) Date: Sat, 13 Mar 2004 16:38:15 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/sprint/Stackless channelobject.c, 1.34, 1.35 scheduling.c, 1.81, 1.82 stackless_structs.h, 1.53, 1.54 stacklessmodule.c, 1.145, 1.146 taskletobject.c, 1.87, 1.88 Message-ID: Update of /home/cvs/slpdev/src/2.3/sprint/Stackless In directory centera.de:/tmp/cvs-serv15596 Modified Files: channelobject.c scheduling.c stackless_structs.h stacklessmodule.c taskletobject.c Log Message: made an #define to toggle soft channel switching, currently off. added a channel field to tasklets, but currently not implemented so it's commented out Index: channelobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/channelobject.c,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** channelobject.c 12 Mar 2004 16:36:31 -0000 1.34 --- channelobject.c 13 Mar 2004 15:38:12 -0000 1.35 *************** *** 11,14 **** --- 11,16 ---- #include "channelobject.h" + #define EXPERIMENTAL_CHANNEL_SOFT_SWITCHING 0 + static void channel_dealloc(PyObject *op) *************** *** 218,221 **** --- 220,311 ---- } + + typedef struct _channel_blocking_frame { + PyBaseFrameObject bf; + PyObject *channel; + PyObject *tasklet; + } channel_blocking_frame; + #define CHANNEL_BLOCKING_FRAME_SIZE ((sizeof(channel_blocking_frame)-sizeof(PyBaseFrameObject))/sizeof(PyObject*)) + + channel_blocking_frame * + channel_blocking_frame_new(PyFrame_ExecFunc *exec, PyObject *channel, PyObject *tasklet) { + channel_blocking_frame *rval = (channel_blocking_frame *)slp_baseframe_new(exec, 1, CHANNEL_BLOCKING_FRAME_SIZE); + if (rval != NULL) { + Py_INCREF(tasklet); + rval->tasklet = tasklet; + Py_INCREF(channel); + rval->channel = channel; + } + return rval; + } + + static PyObject * + channel_blocking_defer(PyFrame_ExecFunc *exec, PyChannelObject *self, PyTaskletObject *tasklet) + { + PyThreadState *ts = PyThreadState_GET(); + PyFrameObject *save = ts->frame; + /* create a helper frame to perform the schedule_remove after return */ + ts->frame = (PyFrameObject *) channel_blocking_frame_new(exec, (PyObject*)self, (PyObject*)tasklet); + if (ts->frame == NULL) { + ts->frame = save; + return NULL; + } + Py_XDECREF(save->f_callee); + Py_INCREF(ts->frame); + save->f_callee = ts->frame; + /* the retval is still in ts->st.tempval, so we're ready */ + return Py_UnwindToken; + } + + static PyObject * + channel_blocking_finished_send(PyFrameObject *f) + { + PyThreadState *ts = PyThreadState_GET(); + channel_blocking_frame *cbf = (channel_blocking_frame *) f; + Py_DECREF(cbf->channel); + Py_DECREF(cbf->tasklet); + ts->frame = f->f_back; + return Py_UnwindToken; + } + + static PyObject * + channel_blocking_finished_recv(PyFrameObject *f) + { + PyThreadState *ts = PyThreadState_GET(); + channel_blocking_frame *cbf = (channel_blocking_frame *) f; + + PyObject *result = ts->st.tempval; + PyObject *rval; + + /* support for exception instances */ + if (PyObject_IsInstance(result, PyExc_Exception)) { + PyObject *type = (PyObject *) ((PyInstanceObject*)result)->in_class; + PyObject *args = PyObject_GetAttrString(result, "args"); + Py_INCREF(type); + /* special case: un-wrap a string exception */ + if (type == PyExc_Exception && args != NULL && PyTuple_Check(args) + && PyTuple_GET_SIZE(args) == 2 && PyString_Check(PyTuple_GET_ITEM(args, 0)) ) { + PyObject *t = PyTuple_GET_ITEM(args, 0); + PyObject *a = PyTuple_GET_ITEM(args, 1); + Py_INCREF(t); + Py_DECREF(type); + type = t; + Py_INCREF(a); + Py_DECREF(result); + result = a; + } + Py_XDECREF(args); + PyErr_Restore(type, result, NULL); + rval = NULL; + } else { + rval = Py_UnwindToken; + } + + Py_DECREF(cbf->channel); + Py_DECREF(cbf->tasklet); + ts->frame = f->f_back; + return rval; + } + static CHANNEL_SEND_HEAD(impl_channel_send_nr) { *************** *** 271,275 **** return NULL; case 1: ! return Py_UnwindToken; } if (slp_schedule_task(sender, receiver)) return NULL; --- 361,365 ---- return NULL; case 1: ! return channel_blocking_defer(channel_blocking_finished_send, self, sender); } if (slp_schedule_task(sender, receiver)) return NULL; *************** *** 368,372 **** --- 458,466 ---- channel_send_nr(PyObject *myself, PyObject *arg) { + #if EXPERIMENTAL_CHANNEL_SOFT_SWITCHING return impl_channel_send_nr((PyChannelObject*)myself, arg); + #else + return impl_channel_send((PyChannelObject*)myself, arg); + #endif } *************** *** 606,610 **** return NULL; case 1: ! return Py_UnwindToken; } --- 700,704 ---- return NULL; case 1: ! return channel_blocking_defer(channel_blocking_finished_recv, self, receiver); } *************** *** 734,738 **** --- 828,836 ---- channel_receive_nr(PyObject *myself) { + #if EXPERIMENTAL_CHANNEL_SOFT_SWITCHING return impl_channel_receive_nr((PyChannelObject*)myself); + #else + return impl_channel_receive((PyChannelObject*)myself); + #endif } Index: scheduling.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/scheduling.c,v retrieving revision 1.81 retrieving revision 1.82 diff -C2 -d -r1.81 -r1.82 *** scheduling.c 12 Mar 2004 15:57:35 -0000 1.81 --- scheduling.c 13 Mar 2004 15:38:12 -0000 1.82 *************** *** 180,183 **** --- 180,185 ---- PyObject *exc_traceback; } exc_frame; + #define EXC_FRAME_SIZE ((sizeof(exc_frame)-sizeof(PyBaseFrameObject))/sizeof(PyObject*)) + static PyObject * *************** *** 191,194 **** --- 193,197 ---- ts->exc_traceback = ef->exc_traceback; ef->exc_type = ef->exc_traceback = ef->exc_value = NULL; + Py_INCREF(f); f->f_callee = (PyFrameObject *) ef; ts->frame = f; *************** *** 259,263 **** else if (ts->exc_type != NULL) { /* build a shadow frame */ ! exc_frame *f = (exc_frame *) slp_baseframe_new(restore_exception, 1, 3); if (f == NULL) return -1; --- 262,266 ---- else if (ts->exc_type != NULL) { /* build a shadow frame */ ! exc_frame *f = (exc_frame *) slp_baseframe_new(restore_exception, 1, EXC_FRAME_SIZE); if (f == NULL) return -1; Index: stackless_structs.h =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/stackless_structs.h,v retrieving revision 1.53 retrieving revision 1.54 diff -C2 -d -r1.53 -r1.54 *** stackless_structs.h 25 Feb 2004 11:14:13 -0000 1.53 --- stackless_structs.h 13 Mar 2004 15:38:12 -0000 1.54 *************** *** 80,83 **** --- 80,86 ---- struct _cframe *cframe; } f; + /* + PyObject *channel; + */ PyFrameObject *topframe; PyObject *tempval; Index: stacklessmodule.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/stacklessmodule.c,v retrieving revision 1.145 retrieving revision 1.146 diff -C2 -d -r1.145 -r1.146 *** stacklessmodule.c 2 Mar 2004 20:31:44 -0000 1.145 --- stacklessmodule.c 13 Mar 2004 15:38:12 -0000 1.146 *************** *** 1047,1050 **** --- 1047,1053 ---- slpmodule_set__channel__(m, &PyChannel_Type, NULL); slpmodule_set__scheduler__(m, &PyScheduler_Type, NULL); + + #undef INSERT + } Index: taskletobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/taskletobject.c,v retrieving revision 1.87 retrieving revision 1.88 diff -C2 -d -r1.87 -r1.88 *** taskletobject.c 12 Mar 2004 15:57:35 -0000 1.87 --- taskletobject.c 13 Mar 2004 15:38:12 -0000 1.88 *************** *** 153,156 **** --- 153,159 ---- Py_DECREF(_hold); \ } + /* + ZAP(t->channel); + */ if (t->topframe != NULL) { *************** *** 206,209 **** --- 209,215 ---- if (t != NULL) { *(int*)&t->flags = 0; + /* + t->channel = NULL; + */ t->next = NULL; t->prev = NULL; *************** *** 290,294 **** PyFrameObject *f; PyThreadState *ts = PyThreadState_GET(); ! int have_tempval = t->tempval != NULL ? 1 : 0; if (t == ts->st.current) return RUNTIME_ERROR("You cannot __reduce__ the tasklet which is current.", NULL); --- 296,300 ---- PyFrameObject *f; PyThreadState *ts = PyThreadState_GET(); ! int have_tempval = (t->tempval != NULL) ? 1 : 0; if (t == ts->st.current) return RUNTIME_ERROR("You cannot __reduce__ the tasklet which is current.", NULL); *************** *** 1245,1248 **** --- 1251,1258 ---- static PyMemberDef tasklet_members[] = { + /* + {"channel", T_OBJECT, offsetof(PyTaskletObject, channel), READONLY, + "The channel this tasklet is blocked on, or None if it is not blocked."}, + */ {"next", T_OBJECT, offsetof(PyTaskletObject, next), READONLY, "the next tasklet in a a circular list of tasklets."}, *************** *** 1266,1271 **** "atomic inhibits scheduling of this tasklet. See setatomic()\n" "Part of the flags word."}, ! ! {"frame", (getter)tasklet_get_frame, NULL, "the current frame of this tasklet. For the running tasklet,\n" "this is redirected to tstate.frame."}, --- 1276,1281 ---- "atomic inhibits scheduling of this tasklet. See setatomic()\n" "Part of the flags word."}, ! ! {"frame", (getter)tasklet_get_frame, NULL, "the current frame of this tasklet. For the running tasklet,\n" "this is redirected to tstate.frame."}, _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From bob at centera.de Sat Mar 13 14:03:27 2004 From: bob at centera.de (Bob Ippolito) Date: Sat, 13 Mar 2004 14:03:27 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/sprint/Stackless switch_ppc_macosx.h, 1.11, 1.12 Message-ID: Update of /home/cvs/slpdev/src/2.3/sprint/Stackless In directory centera.de:/tmp/cvs-serv12253 Modified Files: switch_ppc_macosx.h Log Message: Force full PIC prologue to exist for the best compiler in the world: cc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1636) (-mlongcall) Index: switch_ppc_macosx.h =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/switch_ppc_macosx.h,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** switch_ppc_macosx.h 14 Jan 2004 14:26:54 -0000 1.11 --- switch_ppc_macosx.h 13 Mar 2004 13:03:25 -0000 1.12 *************** *** 36,51 **** "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r31", \ "cr2", "cr3", "cr4" static int slp_switch(void) { register int *stackref, stsizediff; ! __asm__ volatile ("" : : : REGS_TO_SAVE); ! __asm__ ("mr %0, r1" : "=g" (stackref) : ); { SLP_SAVE_STATE(stackref, stsizediff); __asm__ volatile ( ! "mr r11, %0\n" ! "add r1, r1, r11\n" ! "add r30, r30, r11\n" : /* no outputs */ : "g" (stsizediff) --- 36,59 ---- "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r31", \ "cr2", "cr3", "cr4" + static int slp_switch(void) { + static int x = 0; register int *stackref, stsizediff; ! __asm__ volatile ( ! "; asm block 1\n" ! : /* no outputs */ ! : "r" (x) ! : REGS_TO_SAVE ! ); ! __asm__ ("; asm block 2\n\tmr %0, r1" : "=g" (stackref) : ); { SLP_SAVE_STATE(stackref, stsizediff); __asm__ volatile ( ! "; asm block 3\n" ! "\tmr r11, %0\n" ! "\tadd r1, r1, r11\n" ! "\tadd r30, r30, r11\n" : /* no outputs */ : "g" (stsizediff) *************** *** 55,59 **** return 0; } - __asm__ volatile ("" : : : REGS_TO_SAVE); } --- 63,66 ---- _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From tismer at centera.de Fri Mar 12 13:32:13 2004 From: tismer at centera.de (Christian Tismer) Date: Fri, 12 Mar 2004 13:32:13 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/src/Stackless cframeobject.c, 1.56, 1.57 Message-ID: Update of /home/cvs/slpdev/src/2.3/src/Stackless In directory centera.de:/tmp/cvs-serv9629/src/Stackless Modified Files: cframeobject.c Log Message: turned frame->f_back into a computed attribute. baseframes are skipped when f_back is inquired. This should fix certain problems. I also could remove all the baseframe methods which tried to make baseframes look like regular frames. Index: cframeobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/src/Stackless/cframeobject.c,v retrieving revision 1.56 retrieving revision 1.57 diff -C2 -d -r1.56 -r1.57 *** cframeobject.c 16 Feb 2004 18:07:09 -0000 1.56 --- cframeobject.c 12 Mar 2004 12:32:10 -0000 1.57 *************** *** 307,391 **** }; - /* let cframes walk and quack like real frames in the context of a stack trace */ - - static PyObject * - cframe_get_noobj(PyObject *op, void *nope) - { - Py_INCREF(Py_None); - return Py_None; - } - - static int - cframe_set_noobj(PyObject *op, void *context) - { - return 0; - } - - static PyObject * - cframe_get_noint(PyObject *op, void *context) - { - return PyInt_FromLong(0); - } - - static PyObject * - baseframe_get_code(PyObject *op) - { - PyCodeObject *code; - /* compile a dummy code object and put some name in place */ - code = (PyCodeObject *)Py_CompileString("", "", Py_file_input); - if (code != NULL) { - Py_DECREF(code->co_name); - code->co_name = PyString_FromString("(internal)"); - } - return (PyObject*) code; - } - - static PyObject * - cframe_get_code(PyObject *op) - { - PyCFrameObject *c = (PyCFrameObject*) op; - PyCodeObject *code; - /* compile a dummy code object and put some name in place */ - code = (PyCodeObject *)Py_CompileString("", "", Py_file_input); - if (code != NULL) { - Py_DECREF(code->co_name); - code->co_name = PyObject_Repr(c->callable); - } - return (PyObject*) code; - } - - static char baseframe_get_nothing__doc__[] = - "This is a computed dummy field, just for frame compatibility.\n\ - Please refer to the BaseFrame's real properties (params)."; - - - static PyGetSetDef baseframe_getsetlist[] = { - {"f_code", (getter)baseframe_get_code, NULL, baseframe_get_nothing__doc__}, - {"f_lasti", (getter)cframe_get_noint, NULL, baseframe_get_nothing__doc__}, - {"f_lineno", (getter)cframe_get_noint, NULL, baseframe_get_nothing__doc__}, - {"f_restricted", (getter)cframe_get_noint, NULL, baseframe_get_nothing__doc__}, - {"f_trace", (getter)cframe_get_noobj, (setter)cframe_set_noobj, baseframe_get_nothing__doc__}, - {"f_exc_type", (getter)cframe_get_noobj, NULL, baseframe_get_nothing__doc__}, - {"f_exc_value", (getter)cframe_get_noobj, NULL, baseframe_get_nothing__doc__}, - {"f_exc_traceback", (getter)cframe_get_noobj, NULL, baseframe_get_nothing__doc__}, - {NULL} /* Sentinel */ - }; - - static char cframe_get_nothing__doc__[] = - "This is a computed dummy field, just for frame compatibility.\n\ - Please refer to the CFrame's real properties (callable/args/kwds)."; - - - static PyGetSetDef cframe_getsetlist[] = { - {"f_code", (getter)cframe_get_code, NULL, cframe_get_nothing__doc__}, - {"f_lasti", (getter)cframe_get_noint, NULL, cframe_get_nothing__doc__}, - {"f_lineno", (getter)cframe_get_noint, NULL, cframe_get_nothing__doc__}, - {"f_restricted", (getter)cframe_get_noint, NULL, cframe_get_nothing__doc__}, - {"f_trace", (getter)cframe_get_noobj, (setter)cframe_set_noobj, cframe_get_nothing__doc__}, - {"f_exc_type", (getter)cframe_get_noobj, NULL, cframe_get_nothing__doc__}, - {"f_exc_value", (getter)cframe_get_noobj, NULL, cframe_get_nothing__doc__}, - {"f_exc_traceback", (getter)cframe_get_noobj, NULL, cframe_get_nothing__doc__}, - {NULL} /* Sentinel */ - }; PyTypeObject PyBaseFrame_Type = { --- 307,310 ---- *************** *** 420,424 **** baseframe_methods, /* tp_methods */ baseframe_memberlist, /* tp_members */ ! baseframe_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ --- 339,343 ---- baseframe_methods, /* tp_methods */ baseframe_memberlist, /* tp_members */ ! 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ *************** *** 464,468 **** 0, /* tp_methods */ cframe_memberlist, /* tp_members */ ! cframe_getsetlist, /* tp_getset */ &PyBaseFrame_Type, /* tp_base */ 0, /* tp_dict */ --- 383,387 ---- 0, /* tp_methods */ cframe_memberlist, /* tp_members */ ! 0, /* tp_getset */ &PyBaseFrame_Type, /* tp_base */ 0, /* tp_dict */ _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From bob at centera.de Fri Mar 12 17:36:34 2004 From: bob at centera.de (Bob Ippolito) Date: Fri, 12 Mar 2004 17:36:34 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/sprint/Stackless channelobject.c, 1.33, 1.34 Message-ID: Update of /home/cvs/slpdev/src/2.3/sprint/Stackless In directory centera.de:/tmp/cvs-serv17818/Stackless Modified Files: channelobject.c Log Message: had an uninitialized variable being used Index: channelobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/channelobject.c,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** channelobject.c 12 Mar 2004 15:57:35 -0000 1.33 --- channelobject.c 12 Mar 2004 16:36:31 -0000 1.34 *************** *** 334,338 **** Py_INCREF(arg); ts->st.tempval = arg; ! if (slp_schedule_task(sender, receiver)) return NULL; if (ts->st.tempval == NULL) { --- 334,339 ---- Py_INCREF(arg); ts->st.tempval = arg; ! receiver = ts->st.current; ! if (slp_schedule_task(sender, receiver)) return NULL; if (ts->st.tempval == NULL) { _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From tismer at centera.de Thu Mar 25 23:59:09 2004 From: tismer at centera.de (Christian Tismer) Date: Thu, 25 Mar 2004 23:59:09 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/dev/Objects abstract.c, 1.5, 1.6 classobject.c, 1.9, 1.10 descrobject.c, 1.4, 1.5 funcobject.c, 1.3, 1.4 methodobject.c, 1.4, 1.5 typeobject.c, 1.7, 1.8 Message-ID: Update of /home/cvs/slpdev/src/2.3/dev/Objects In directory centera.de:/tmp/cvs-serv16011/Objects Modified Files: abstract.c classobject.c descrobject.c funcobject.c methodobject.c typeobject.c Log Message: A quite huge change was made! The xxx_nr functions are all gone. There is now an implicit parameter in slp_try_stackless and a couple of macros which support this. tp_iternext_nr is also gone. Generator.next is now also stackless. raise_exception and kill are stackless, too. due to the new calling convention. nonrecursive.c is completely gone. A lot of extra functions could be removed. Please see the comments in stackless_impl.h and the use of the macros in the various files. Control over stackless behavior is now done by a new type flag Py_TPFLAGS_HAVE_STACKLESS_CALL, a new PyCFunction flag METH_STACKLESS and a new wrapper flag PyWrapperFlag_STACKLESS. A small change on conventions: If only macros like STACKLES_XXX are used, they are not embraced into #ifdef STACKLESS constructs. They are expanding to nothing if STACKLESS is undefined. Index: abstract.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/dev/Objects/abstract.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** abstract.c 14 Jan 2004 19:11:08 -0000 1.5 --- abstract.c 25 Mar 2004 22:59:06 -0000 1.6 *************** *** 5,8 **** --- 5,9 ---- #include "structmember.h" /* we need the offsetof() macro from there */ #include "longintrepr.h" + #include "stackless_impl.h" #define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \ *************** *** 1751,1757 **** --- 1752,1766 ---- { ternaryfunc call; + STACKLESS_GETARG(); if ((call = func->ob_type->tp_call) != NULL) { + #ifdef STACKLESS + PyObject *result; + STACKLESS_PROMOTE(func); + result = (*call)(func, arg, kw); + STACKLESS_ASSERT(); + #else PyObject *result = (*call)(func, arg, kw); + #endif if (result == NULL && !PyErr_Occurred()) PyErr_SetString( *************** *** 1770,1773 **** --- 1779,1783 ---- va_list va; PyObject *args, *retval; + STACKLESS_GETARG(); if (callable == NULL) *************** *** 1795,1799 **** --- 1805,1811 ---- args = a; } + STACKLESS_PROMOTE(callable); retval = PyObject_Call(callable, args, NULL); + STACKLESS_ASSERT(); Py_DECREF(args); *************** *** 1807,1810 **** --- 1819,1823 ---- va_list va; PyObject *args, *func = 0, *retval; + STACKLESS_GETARG(); if (o == NULL || name == NULL) *************** *** 1842,1846 **** --- 1855,1861 ---- } + STACKLESS_PROMOTE(func); retval = PyObject_Call(func, args, NULL); + STACKLESS_ASSERT(); Py_DECREF(args); *************** *** 1886,1889 **** --- 1901,1905 ---- PyObject *args, *tmp; va_list vargs; + STACKLESS_GETARG(); if (callable == NULL || name == NULL) *************** *** 1902,1906 **** --- 1918,1924 ---- return NULL; } + STACKLESS_PROMOTE(callable); tmp = PyObject_Call(callable, args, NULL); + STACKLESS_ASSERT(); Py_DECREF(args); Py_DECREF(callable); *************** *** 1914,1917 **** --- 1932,1936 ---- PyObject *args, *tmp; va_list vargs; + STACKLESS_GETARG(); if (callable == NULL) *************** *** 1924,1928 **** --- 1943,1949 ---- if (args == NULL) return NULL; + STACKLESS_PROMOTE(callable); tmp = PyObject_Call(callable, args, NULL); + STACKLESS_ASSERT(); Py_DECREF(args); *************** *** 2183,2188 **** --- 2204,2215 ---- { PyObject *result; + STACKLESS_GETARG(); assert(PyIter_Check(iter)); + #ifdef STACKLESS + /* we use the same flag here, since iterators are not callable */ + #endif + STACKLESS_PROMOTE(iter); result = (*iter->ob_type->tp_iternext)(iter); + STACKLESS_ASSERT(); if (result == NULL && PyErr_Occurred() && Index: classobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/dev/Objects/classobject.c,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** classobject.c 17 Feb 2004 16:33:58 -0000 1.9 --- classobject.c 25 Mar 2004 22:59:06 -0000 1.10 *************** *** 4,7 **** --- 4,8 ---- #include "Python.h" #include "structmember.h" + #include "stackless_impl.h" #define TP_DESCR_GET(t) \ *************** *** 2409,2412 **** --- 2410,2414 ---- PyObject *class = PyMethod_GET_CLASS(func); PyObject *result; + STACKLESS_GETARG(); func = PyMethod_GET_FUNCTION(func); *************** *** 2457,2461 **** --- 2459,2465 ---- arg = newarg; } + STACKLESS_PROMOTE(func); result = PyObject_Call((PyObject *)func, arg, kw); + STACKLESS_ASSERT(); Py_DECREF(arg); return result; *************** *** 2509,2513 **** --- 2513,2521 ---- PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ + #ifdef STACKLESS + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_STACKLESS_CALL,/* tp_flags */ + #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + #endif instancemethod_doc, /* tp_doc */ (traverseproc)instancemethod_traverse, /* tp_traverse */ Index: descrobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/dev/Objects/descrobject.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** descrobject.c 14 Jan 2004 19:11:08 -0000 1.4 --- descrobject.c 25 Mar 2004 22:59:06 -0000 1.5 *************** *** 3,6 **** --- 3,7 ---- #include "Python.h" #include "structmember.h" /* Why is this not included in Python.h? */ + #include "stackless_impl.h" static void *************** *** 13,21 **** } - #ifdef STACKLESS - char * - #else static char * - #endif descr_name(PyDescrObject *descr) { --- 14,18 ---- *************** *** 216,219 **** --- 213,217 ---- int argc; PyObject *self, *func, *result; + STACKLESS_GETARG(); /* Make sure that the first argument is acceptable as 'self' */ *************** *** 248,252 **** --- 246,252 ---- return NULL; } + STACKLESS_PROMOTE(func); result = PyEval_CallObjectWithKeywords(func, args, kwds); + STACKLESS_ASSERT(); Py_DECREF(args); Py_DECREF(func); *************** *** 259,262 **** --- 259,263 ---- { PyObject *func, *result; + STACKLESS_GETARG(); func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type); *************** *** 264,268 **** --- 265,271 ---- return NULL; + STACKLESS_PROMOTE(func); result = PyEval_CallObjectWithKeywords(func, args, kwds); + STACKLESS_ASSERT(); Py_DECREF(func); return result; *************** *** 274,277 **** --- 277,281 ---- int argc; PyObject *self, *func, *result; + STACKLESS_GETARG(); /* Make sure that the first argument is acceptable as 'self' */ *************** *** 306,310 **** --- 310,316 ---- return NULL; } + STACKLESS_PROMOTE(func); result = PyEval_CallObjectWithKeywords(func, args, kwds); + STACKLESS_ASSERT(); Py_DECREF(args); Py_DECREF(func); *************** *** 417,421 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ descr_traverse, /* tp_traverse */ --- 423,431 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! #ifdef STACKLESS ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_STACKLESS_CALL,/* tp_flags */ ! #else ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ ! #endif 0, /* tp_doc */ descr_traverse, /* tp_traverse */ *************** *** 456,460 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ descr_traverse, /* tp_traverse */ --- 466,474 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! #ifdef STACKLESS ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_STACKLESS_CALL,/* tp_flags */ ! #else ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ ! #endif 0, /* tp_doc */ descr_traverse, /* tp_traverse */ *************** *** 570,574 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ descr_traverse, /* tp_traverse */ --- 584,592 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! #ifdef STACKLESS ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_STACKLESS_CALL,/* tp_flags */ ! #else ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ ! #endif 0, /* tp_doc */ descr_traverse, /* tp_traverse */ *************** *** 951,954 **** --- 969,985 ---- }; + #ifdef STACKLESS + #define WRAP_RETURN(call) { \ + PyObject * retval; \ + STACKLESS_PROMOTE_FLAG(wp->descr->d_base->flags & PyWrapperFlag_STACKLESS \ + && wp->descr->d_type->tp_flags & Py_TPFLAGS_HAVE_STACKLESS_CALL); \ + retval = (call); \ + STACKLESS_ASSERT(); \ + return retval; \ + } + #else + #define WRAP_RETURN(call) return (call) + #endif + static PyObject * wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds) *************** *** 956,963 **** wrapperfunc wrapper = wp->descr->d_base->wrapper; PyObject *self = wp->self; if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) { wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper; ! return (*wk)(self, args, wp->descr->d_wrapped, kwds); } --- 987,995 ---- wrapperfunc wrapper = wp->descr->d_base->wrapper; PyObject *self = wp->self; + STACKLESS_GETARG(); if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) { wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper; ! WRAP_RETURN( (*wk)(self, args, wp->descr->d_wrapped, kwds) ); } *************** *** 968,972 **** return NULL; } ! return (*wrapper)(self, args, wp->descr->d_wrapped); } --- 1000,1004 ---- return NULL; } ! WRAP_RETURN( (*wrapper)(self, args, wp->descr->d_wrapped) ); } *************** *** 1012,1016 **** 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ wrapper_traverse, /* tp_traverse */ --- 1044,1052 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ ! #ifdef STACKLESS ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_STACKLESS_CALL,/* tp_flags */ ! #else ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ ! #endif 0, /* tp_doc */ wrapper_traverse, /* tp_traverse */ Index: funcobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/dev/Objects/funcobject.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** funcobject.c 14 Jan 2004 19:11:08 -0000 1.3 --- funcobject.c 25 Mar 2004 22:59:06 -0000 1.4 *************** *** 6,9 **** --- 6,10 ---- #include "eval.h" #include "structmember.h" + #include "stackless_impl.h" PyObject * *************** *** 472,475 **** --- 473,477 ---- PyObject **d, **k; int nk, nd; + STACKLESS_GETARG(); argdefs = PyFunction_GET_DEFAULTS(func); *************** *** 502,505 **** --- 504,508 ---- } + STACKLESS_PROMOTE(func); result = PyEval_EvalCodeEx( (PyCodeObject *)PyFunction_GET_CODE(func), *************** *** 508,511 **** --- 511,515 ---- k, nk, d, nd, PyFunction_GET_CLOSURE(func)); + STACKLESS_ASSERT(); if (k != NULL) *************** *** 545,549 **** --- 549,557 ---- PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ + #ifdef STACKLESS + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_STACKLESS_CALL,/* tp_flags */ + #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + #endif func_doc, /* tp_doc */ (traverseproc)func_traverse, /* tp_traverse */ Index: methodobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/dev/Objects/methodobject.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** methodobject.c 14 Jan 2004 19:11:08 -0000 1.4 --- methodobject.c 25 Mar 2004 22:59:06 -0000 1.5 *************** *** 4,7 **** --- 4,8 ---- #include "Python.h" #include "structmember.h" + #include "stackless_impl.h" static PyCFunctionObject *free_list = NULL; *************** *** 22,31 **** } op->m_ml = ml; - #ifdef STACKLESS - { - int nr_dist = ml->ml_flags >> METH_SHIFT; - op->m_meth_nr = (ml+nr_dist)->ml_meth; - } - #endif Py_XINCREF(self); op->m_self = self; --- 23,26 ---- *************** *** 63,72 **** return -1; } #ifdef STACKLESS ! return ((PyCFunctionObject *)op) -> m_ml -> ml_flags & METH_MASK; #else ! return ((PyCFunctionObject *)op) -> m_ml -> ml_flags; #endif - } PyObject * --- 58,75 ---- return -1; } + return ((PyCFunctionObject *)op) -> m_ml -> ml_flags; + } + #ifdef STACKLESS ! #define WRAP_RETURN(call) { \ ! PyObject * retval; \ ! STACKLESS_PROMOTE_FLAG(PyCFunction_GET_FLAGS(func) & METH_STACKLESS); \ ! retval = (call); \ ! STACKLESS_ASSERT(); \ ! return retval; \ ! } #else ! #define WRAP_RETURN(call) return (call) #endif PyObject * *************** *** 77,94 **** PyObject *self = PyCFunction_GET_SELF(func); int size; switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC)) { case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) ! return (*meth)(self, arg); break; case METH_VARARGS | METH_KEYWORDS: case METH_OLDARGS | METH_KEYWORDS: ! return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 0) ! return (*meth)(self, NULL); PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%d given)", --- 80,102 ---- PyObject *self = PyCFunction_GET_SELF(func); int size; + STACKLESS_GETARG(); + #ifdef STACKLESS + switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_STACKLESS)) { + #else switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC)) { + #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 (%d given)", *************** *** 101,105 **** size = PyTuple_GET_SIZE(arg); if (size == 1) ! return (*meth)(self, PyTuple_GET_ITEM(arg, 0)); PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%d given)", --- 109,113 ---- 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 (%d given)", *************** *** 116,120 **** else if (size == 0) arg = NULL; ! return (*meth)(self, arg); } break; --- 124,128 ---- else if (size == 0) arg = NULL; ! WRAP_RETURN( (*meth)(self, arg) ); } break; *************** *** 271,275 **** --- 279,287 ---- 0, /* tp_setattro */ 0, /* tp_as_buffer */ + #ifdef STACKLESS + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_STACKLESS_CALL,/* tp_flags */ + #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + #endif 0, /* tp_doc */ (traverseproc)meth_traverse, /* tp_traverse */ Index: typeobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/dev/Objects/typeobject.c,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** typeobject.c 24 Mar 2004 16:27:08 -0000 1.7 --- typeobject.c 25 Mar 2004 22:59:06 -0000 1.8 *************** *** 3,6 **** --- 3,7 ---- #include "Python.h" #include "structmember.h" + #include "stackless_impl.h" #include *************** *** 896,899 **** --- 897,901 ---- va_list va; PyObject *args, *func = 0, *retval; + STACKLESS_GETARG(); va_start(va, format); *************** *** 917,921 **** --- 919,925 ---- assert(PyTuple_Check(args)); + STACKLESS_PROMOTE(func); retval = PyObject_Call(func, args, NULL); + STACKLESS_ASSERT(); Py_DECREF(args); *************** *** 932,935 **** --- 936,940 ---- va_list va; PyObject *args, *func = 0, *retval; + STACKLESS_GETARG(); va_start(va, format); *************** *** 955,959 **** --- 960,966 ---- assert(PyTuple_Check(args)); + STACKLESS_PROMOTE(func); retval = PyObject_Call(func, args, NULL); + STACKLESS_ASSERT(); Py_DECREF(args); *************** *** 3056,3062 **** /* tp_hash see tp_richcompare */ COPYSLOT(tp_call); - #ifdef STACKLESS - COPYSLOT(tp_call_nr); - #endif COPYSLOT(tp_str); if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) { --- 3063,3066 ---- *************** *** 3076,3082 **** COPYSLOT(tp_iter); COPYSLOT(tp_iternext); - #ifdef STACKLESS - COPYSLOT(tp_iternext_nr); - #endif } if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) { --- 3080,3083 ---- *************** *** 3258,3269 **** } - #ifdef STACKLESS - /* fill in the extra _nr slots */ - if (type->tp_call_nr == NULL) - type->tp_call_nr = type->tp_call; - if (type->tp_iternext_nr == NULL) - type->tp_iternext_nr = type->tp_iternext; - #endif - /* All done -- set the ready flag */ assert(type->tp_dict != NULL); --- 3259,3262 ---- *************** *** 5044,5049 **** --- 5037,5048 ---- TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc, "x.__iter__() <==> iter(x)"), + #ifdef STACKLESS + FLSLOT("next", tp_iternext, slot_tp_iternext, wrap_next, + "x.next() -> the next value, or raise StopIteration", + PyWrapperFlag_STACKLESS), + #else TPSLOT("next", tp_iternext, slot_tp_iternext, wrap_next, "x.next() -> the next value, or raise StopIteration"), + #endif TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get, "descr.__get__(obj[, type]) -> value"), _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From tismer at centera.de Sun Mar 14 14:14:56 2004 From: tismer at centera.de (Christian Tismer) Date: Sun, 14 Mar 2004 14:14:56 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/sprint/Stackless stackless_structs.h, 1.54, 1.55 stacklessmodule.c, 1.148, 1.149 atomicobject.c, 1.16, NONE atomicobject.h, 1.2, NONE Message-ID: Update of /home/cvs/slpdev/src/2.3/sprint/Stackless In directory centera.de:/tmp/cvs-serv18722 Modified Files: stackless_structs.h stacklessmodule.c Removed Files: atomicobject.c atomicobject.h Log Message: removed the atomic object. After there exists garbage collection, it is probably a bad idea to rely on it. We might instead add a wrapper function to the module that runs something atomically. Any proposals for a name? Index: stackless_structs.h =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/stackless_structs.h,v retrieving revision 1.54 retrieving revision 1.55 diff -C2 -d -r1.54 -r1.55 *** stackless_structs.h 13 Mar 2004 15:38:12 -0000 1.54 --- stackless_structs.h 14 Mar 2004 13:14:53 -0000 1.55 *************** *** 206,214 **** #define PyChannel_CheckExact(op) ((op)->ob_type == PyChannel_TypePtr) - PyAPI_DATA(PyTypeObject*) PyAtomic_TypePtr; - #define PyAtomic_Type (*PyAtomic_TypePtr) - #define PyAtomic_Check(op) PyObject_TypeCheck(op, PyAtomic_TypePtr) - #define PyAtomic_CheckExact(op) ((op)->ob_type == PyAtomic_TypePtr) - PyAPI_DATA(PyTypeObject*) PyScheduler_TypePtr; #define PyScheduler_Type (*PyScheduler_TypePtr) --- 206,209 ---- Index: stacklessmodule.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/stacklessmodule.c,v retrieving revision 1.148 retrieving revision 1.149 diff -C2 -d -r1.148 -r1.149 *** stacklessmodule.c 13 Mar 2004 18:31:02 -0000 1.148 --- stacklessmodule.c 14 Mar 2004 13:14:53 -0000 1.149 *************** *** 8,12 **** #define IMPLEMENT_STACKLESSMODULE #include "slp_platformselect.h" - #include "atomicobject.h" #include "cframeobject.h" #include "taskletobject.h" --- 8,11 ---- *************** *** 968,972 **** if (0 - || init_atomictype() || init_tasklettype() || init_channeltype() --- 967,970 ---- *************** *** 979,983 **** INSERT("cstack", &PyCStack_Type); INSERT("tasklet", &PyTasklet_Type); - INSERT("atomic", &PyAtomic_Type); INSERT("channel", &PyChannel_Type); INSERT("scheduler", &PyScheduler_Type); --- 977,980 ---- --- atomicobject.c DELETED --- --- atomicobject.h DELETED --- _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From rxe at centera.de Sat Mar 13 11:00:48 2004 From: rxe at centera.de (Richard Emslie) Date: Sat, 13 Mar 2004 11:00:48 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/sprint/Stackless/unittests test_watchdog.py, NONE, 1.1 Message-ID: Update of /home/cvs/slpdev/src/2.3/sprint/Stackless/unittests In directory centera.de:/tmp/cvs-serv7645 Added Files: test_watchdog.py Log Message: Some hacked up unit tests for testing new soft watchdog functionality. Currently, with hard switching, all the tests run successfully except for test_pickle(). This is because C state cannot be restored. --- NEW FILE: test_watchdog.py --- import pickle import unittest import stackless # Helpers class SimpleScheduler(object): """ Not really scheduler as such but used here to implement autoscheduling hack and store a schedule count. """ def __init__(self, bytecodes = 25): self.bytecodes = bytecodes self.schedule_count = 0 def get_schedule_count(self): return self.schedule_count def schedule_cb(self, task): self.schedule_count += 1 task.insert() def autoschedule(self): while stackless.runcount > 1: try: returned = stackless.run(self.bytecodes) except Exception, e: # Can't clear off exception easily... while stackless.runcount > 1: stackless.current.next.kill() raise e else: if returned: self.schedule_cb(returned) def runtask6(name): me = stackless.getcurrent() cur_depth = me.recursion_depth for ii in xrange(1000): assert cur_depth == me.recursion_depth def runtask(name): x = 0 for ii in xrange(1000): pass x += 1 return name def runtask2(name): x = 0 for ii in xrange(1000): if ii % 50: stackless.schedule() x += 1 return name def runtask3(name): exec """ for ii in xrange(1000): pass """ def runtask4(name, channel): for ii in xrange(1000): if ii % 50 == 0: channel.send(name) def recurse_level_then_do_schedule(count): if count == 0: stackless.schedule() else: recurse_level_then_do_schedule(count - 1) def runtask5(name): for ii in [1, 10, 100, 500]: recurse_level_then_do_schedule(ii) def runtask_atomic_helper(count): s = stackless.atomic() for ii in xrange(count): pass def runtask_atomic(name): for ii in xrange(10): for ii in [1, 10, 100, 500]: runtask_atomic_helper(ii) def runtask_bad(name): raise UserWarning class ServerTasklet(stackless.tasklet): def __init__(self, func, name=None): stackless.tasklet.__init__(self, func) if not name: name = "at %08x" % (id(self)) self.name = name def __new__(self, func, name=None): return stackless.tasklet.__new__(self, func) def __repr__(self): return "Tasklet %s" % self.name def servertask(name, chan): self = stackless.getcurrent() self.count = 0 while True: r = chan.receive() self.count += 1 class TestWatchdog(unittest.TestCase): def run_tasklets(self, fn): scheduler = SimpleScheduler(100) tasklets = [] for name in ["t1", "t2", "t3"]: tasklets.append(stackless.tasklet(fn)(name)) scheduler.autoschedule() for ii in tasklets: self.failIf(ii.alive) return scheduler.get_schedule_count() def test_simple(self): self.run_tasklets(runtask) def test_recursion_count(self): self.run_tasklets(runtask6) def test_nested(self): self.run_tasklets(runtask5) def test_tasklet_with_schedule(self): self.failUnless(self.run_tasklets(runtask2) > self.run_tasklets(runtask)) def test_exec_tasklet(self): self.run_tasklets(runtask3) def test_send_recv(self): chan = stackless.channel() server = ServerTasklet(servertask) server_task = server("server", chan) scheduler = SimpleScheduler(100) for name in ["client1", "client2", "client3"]: stackless.tasklet(runtask4)(name, chan) scheduler.autoschedule() self.assertEquals(server.count, 60) def test_atomic(self): self.run_tasklets(runtask_atomic) def test_exception(self): self.failUnlessRaises(UserWarning, lambda:self.run_tasklets(runtask_bad)) def get_pickled_tasklet(self): orig = stackless.tasklet(runtask)("pickleme") not_finished = stackless.run(100) self.assertEqual(not_finished, orig) return pickle.dumps(not_finished) def test_pickle(self): t = pickle.loads(self.get_pickled_tasklet()) t.run() if __name__ == '__main__': import sys if not sys.argv[1:]: sys.argv.append('-v') unittest.main() _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From bob at centera.de Fri Mar 12 16:57:38 2004 From: bob at centera.de (Bob Ippolito) Date: Fri, 12 Mar 2004 16:57:38 +0100 Subject: [Stackless-checkins] CVS: slpdev/src/2.3/sprint/Stackless channelobject.c, 1.32, 1.33 channelobject.h, 1.2, 1.3 scheduling.c, 1.80, 1.81 taskletobject.c, 1.86, 1.87 taskletobject.h, 1.8, 1.9 Message-ID: Update of /home/cvs/slpdev/src/2.3/sprint/Stackless In directory centera.de:/tmp/cvs-serv16626 Modified Files: channelobject.c channelobject.h scheduling.c taskletobject.c taskletobject.h Log Message: Experimental soft switching for channels. Goes into an infinite loop if you do: tasklet(lambda: channel().receive())() run() This has something to do with garbage collection and the tasklet killing by exception. Index: channelobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/channelobject.c,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** channelobject.c 29 Jan 2004 22:43:57 -0000 1.32 --- channelobject.c 12 Mar 2004 15:57:35 -0000 1.33 *************** *** 198,206 **** ! static int PyChannel_Send_M(PyChannelObject *self, PyObject *arg) { ! PyObject *ret = PyStackless_CallMethod_Main((PyObject *) self, "send", "(O)", arg); ! return slp_return_wrapper(ret); } --- 198,212 ---- ! static PyObject * PyChannel_Send_M(PyChannelObject *self, PyObject *arg) { ! return PyStackless_CallMethod_Main((PyObject *) self, "send", "(O)", arg); ! } ! ! int ! PyChannel_Send_nr(PyChannelObject *self, PyObject *arg) ! { ! PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; ! return slp_return_wrapper(t->send_nr(self, arg)); } *************** *** 209,219 **** { PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; ! return t->send(self, arg); } ! static int impl_channel_send(PyChannelObject *self, PyObject *arg) { PyThreadState *ts = PyThreadState_GET(); PyTaskletObject *sender, *receiver; if (ts->st.main == NULL) return PyChannel_Send_M(self, arg); --- 215,227 ---- { PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; ! return slp_return_wrapper(t->send(self, arg)); } ! static CHANNEL_SEND_HEAD(impl_channel_send_nr) { PyThreadState *ts = PyThreadState_GET(); PyTaskletObject *sender, *receiver; + PyObject *ret; + assert(PyChannel_Check(self)); if (ts->st.main == NULL) return PyChannel_Send_M(self, arg); *************** *** 224,229 **** receiver = slp_channel_remove(self, -1); receiver->flags.blocked = 0; - receiver->tempval = arg; Py_INCREF(arg); /* move sender at the end of runnables */ ts->st.current = (PyTaskletObject*)sender->next; --- 232,237 ---- receiver = slp_channel_remove(self, -1); receiver->flags.blocked = 0; Py_INCREF(arg); + receiver->tempval = arg; /* move sender at the end of runnables */ ts->st.current = (PyTaskletObject*)sender->next; *************** *** 231,255 **** slp_current_insert(receiver); ! NOTIFY_SEND(self, sender, 0, -1); ! Py_INCREF(Py_None); ! ts->st.tempval = Py_None; ! if (slp_schedule_task(sender, receiver)) return -1; ! if (ts->st.tempval == NULL) return -1; } else { /* Sending 2): there is nobody listening */ if (ts->st.flags.block_trap) ! return RUNTIME_ERROR("this tasklet does not like to be blocked.", -1); if (ts->st.runcount == 1 && slp_revive_main()) ! return RUNTIME_ERROR("the last runnable tasklet cannot be blocked.", -1); slp_current_remove(); ts->st.flags.blocked = 1; slp_channel_insert(self, sender, 1); ! NOTIFY_SEND(self, sender, 1, -1); ts->st.tempval = arg; Py_INCREF(arg); ! if (slp_schedule_task(sender, ts->st.current)) return -1; if (ts->st.tempval == NULL) { - /* reactivate on exception */ if (sender->flags.blocked) { /* they *might* have invented code to unblock me early :-) */ --- 239,340 ---- slp_current_insert(receiver); ! NOTIFY_SEND(self, sender, 0, NULL); ! ! Py_INCREF(Py_None); ! ts->st.tempval = Py_None; ! ! switch (slp_schedule_nr_maybe(sender, receiver)) { ! case -1: ! return NULL; ! case 1: ! return Py_UnwindToken; ! } ! if (slp_schedule_task(sender, receiver)) return NULL; ! if (ts->st.tempval == NULL) return NULL; } else { /* Sending 2): there is nobody listening */ if (ts->st.flags.block_trap) ! return RUNTIME_ERROR("this tasklet does not like to be blocked.", NULL); if (ts->st.runcount == 1 && slp_revive_main()) ! return RUNTIME_ERROR("the last runnable tasklet cannot be blocked.", NULL); slp_current_remove(); ts->st.flags.blocked = 1; slp_channel_insert(self, sender, 1); ! NOTIFY_SEND(self, sender, 1, NULL); ! Py_INCREF(arg); ts->st.tempval = arg; + receiver = ts->st.current; + + switch (slp_schedule_nr_maybe(sender, receiver)) { + case -1: + return NULL; + case 1: + return Py_UnwindToken; + } + if (slp_schedule_task(sender, receiver)) return NULL; + if (ts->st.tempval == NULL) { + if (sender->flags.blocked) { + /* they *might* have invented code to unblock me early :-) */ + slp_channel_remove_specific(self, 1, sender); + sender->flags.blocked = 0; + slp_current_insert(sender); + ts->st.current = sender; + } + return NULL; + } + + } + ret = ts->st.tempval; + ts->st.tempval = NULL; + return ret; + + } + + + static CHANNEL_SEND_HEAD(impl_channel_send) + { + PyThreadState *ts = PyThreadState_GET(); + PyTaskletObject *sender, *receiver; + PyObject *ret; + assert(PyChannel_Check(self)); + if (ts->st.main == NULL) return PyChannel_Send_M(self, arg); + + sender = ts->st.current; + assert(PyTasklet_Check(sender)); + if (self->balance < 0) { + /* Sending 1): there is somebody listening */ + receiver = slp_channel_remove(self, -1); + receiver->flags.blocked = 0; Py_INCREF(arg); ! receiver->tempval = arg; ! /* move sender at the end of runnables */ ! ts->st.current = (PyTaskletObject*)sender->next; ! /* insert the receiver before the sender */ ! slp_current_insert(receiver); ! ! NOTIFY_SEND(self, sender, 0, NULL); ! ! Py_INCREF(Py_None); ! ts->st.tempval = Py_None; ! ! if (slp_schedule_task(sender, receiver)) return NULL; ! if (ts->st.tempval == NULL) return NULL; ! } ! else { ! /* Sending 2): there is nobody listening */ ! if (ts->st.flags.block_trap) ! return RUNTIME_ERROR("this tasklet does not like to be blocked.", NULL); ! if (ts->st.runcount == 1 && slp_revive_main()) ! return RUNTIME_ERROR("the last runnable tasklet cannot be blocked.", NULL); ! slp_current_remove(); ! ts->st.flags.blocked = 1; ! slp_channel_insert(self, sender, 1); ! NOTIFY_SEND(self, sender, 1, NULL); ! Py_INCREF(arg); ! ts->st.tempval = arg; ! ! if (slp_schedule_task(sender, receiver)) return NULL; if (ts->st.tempval == NULL) { if (sender->flags.blocked) { /* they *might* have invented code to unblock me early :-) */ *************** *** 259,275 **** ts->st.current = sender; } ! return -1; } } ! Py_DECREF(ts->st.tempval); ! ts->st.tempval = NULL; ! return 0; } static CHANNEL_SEND_HEAD(wrap_channel_send) { ! PyObject * ret = PyObject_CallMethod((PyObject *) self, "send", "(O)", arg); ! return slp_return_wrapper(ret); } --- 344,371 ---- ts->st.current = sender; } ! return NULL; } + } ! ret = ts->st.tempval; ! ts->st.tempval = NULL; ! return ret; } + static CHANNEL_SEND_HEAD(wrap_channel_send_nr) + { + return PyObject_CallMethod_nr((PyObject *) self, "send", "(O)", arg); + } + static CHANNEL_SEND_HEAD(wrap_channel_send) { ! return PyObject_CallMethod((PyObject *) self, "send", "(O)", arg); ! } ! ! static PyObject * ! channel_send_nr(PyObject *myself, PyObject *arg) ! { ! return impl_channel_send_nr((PyChannelObject*)myself, arg); } *************** *** 277,284 **** channel_send(PyObject *myself, PyObject *arg) { ! if (impl_channel_send((PyChannelObject*)myself, arg)) ! return NULL; ! Py_INCREF(Py_None); ! return Py_None; } --- 373,377 ---- channel_send(PyObject *myself, PyObject *arg) { ! return impl_channel_send((PyChannelObject*)myself, arg); } *************** *** 290,304 **** channel.send(exception_instance) has the same effect."; ! static int PyChannel_SendException_M(PyChannelObject *self, PyObject *klass, PyObject *args) { ! PyObject *ret = PyStackless_CallMethod_Main((PyObject *) self, "send_exception", "(OO)", klass, args); ! return slp_return_wrapper(ret); } ! int PyChannel_SendException(PyChannelObject *self, PyObject *klass, PyObject *args) { PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; ! return t->send_exception(self, klass, args); } --- 383,438 ---- channel.send(exception_instance) has the same effect."; ! static PyObject * PyChannel_SendException_M(PyChannelObject *self, PyObject *klass, PyObject *args) { ! return PyStackless_CallMethod_Main((PyObject *) self, "send_exception", "(OO)", klass, args); } ! int ! PyChannel_SendException_nr(PyChannelObject *self, PyObject *klass, PyObject *args) { PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; ! return slp_return_wrapper(t->send_exception_nr(self, klass, args)); ! } ! ! int ! PyChannel_SendException(PyChannelObject *self, PyObject *klass, PyObject *args) ! { ! PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; ! return slp_return_wrapper(t->send_exception(self, klass, args)); ! } ! ! static CHANNEL_SEND_EXCEPTION_HEAD(impl_channel_send_exception_nr) ! { ! PyThreadState *ts = PyThreadState_GET(); ! PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; ! PyObject *exc = NULL; ! PyObject *ret; ! assert(PyChannel_Check(self)); ! if (ts->st.main == NULL) return PyChannel_SendException_M(self, klass, args); ! ! if (! (PyObject_IsSubclass(klass, PyExc_Exception) == 1)) { ! if (! PyString_Check(klass) ) ! return TYPE_ERROR("channel.send_exception needs Exception or string subclass as first parameter", NULL); ! /* we got a string instead of a class. Wrap a dummy around */ ! args = Py_BuildValue("(OO)", klass, args); ! klass = PyExc_Exception; ! } ! else { ! if (! PyTuple_Check(args) ) { ! args = Py_BuildValue("(O)", args); ! } ! else { ! Py_INCREF(args); ! } ! } ! if (args != NULL) ! exc = PyObject_Call(klass, args, NULL); ! Py_XDECREF(args); ! if (exc == NULL) ! return NULL; ! ret = t->send_nr(self, exc); ! Py_DECREF(exc); ! return ret; } *************** *** 308,332 **** PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; PyObject *exc = NULL; ! int ret; if (ts->st.main == NULL) return PyChannel_SendException_M(self, klass, args); if (! (PyObject_IsSubclass(klass, PyExc_Exception) == 1)) { if (! PyString_Check(klass) ) ! return TYPE_ERROR("channel.send_exception needs Exception or string subclass as first parameter", -1); /* we got a string instead of a class. Wrap a dummy around */ args = Py_BuildValue("(OO)", klass, args); klass = PyExc_Exception; } ! else if (! PyTuple_Check(args) ) { args = Py_BuildValue("(O)", args); } ! else Py_INCREF(args); if (args != NULL) exc = PyObject_Call(klass, args, NULL); Py_XDECREF(args); if (exc == NULL) ! return -1; ret = t->send(self, exc); Py_DECREF(exc); --- 442,469 ---- PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; PyObject *exc = NULL; ! PyObject *ret; ! assert(PyChannel_Check(self)); if (ts->st.main == NULL) return PyChannel_SendException_M(self, klass, args); if (! (PyObject_IsSubclass(klass, PyExc_Exception) == 1)) { if (! PyString_Check(klass) ) ! return TYPE_ERROR("channel.send_exception needs Exception or string subclass as first parameter", NULL); /* we got a string instead of a class. Wrap a dummy around */ args = Py_BuildValue("(OO)", klass, args); klass = PyExc_Exception; } ! else { if (! PyTuple_Check(args) ) { args = Py_BuildValue("(O)", args); } ! else { Py_INCREF(args); + } + } if (args != NULL) exc = PyObject_Call(klass, args, NULL); Py_XDECREF(args); if (exc == NULL) ! return NULL; ret = t->send(self, exc); Py_DECREF(exc); *************** *** 334,341 **** } static CHANNEL_SEND_EXCEPTION_HEAD(wrap_channel_send_exception) { ! PyObject *ret = PyObject_CallMethod((PyObject *) self, "send_exception", "(OO)", klass, args); ! return slp_return_wrapper(ret); } --- 471,511 ---- } + static CHANNEL_SEND_EXCEPTION_HEAD(wrap_channel_send_exception_nr) + { + return PyObject_CallMethod_nr((PyObject *) self, "send_exception", "(OO)", klass, args); + } + static CHANNEL_SEND_EXCEPTION_HEAD(wrap_channel_send_exception) { ! return PyObject_CallMethod((PyObject *) self, "send_exception", "(OO)", klass, args); ! } ! ! static PyObject * ! channel_send_exception_nr(PyObject *myself, PyObject *args) ! { ! PyObject *result = NULL; ! PyObject *klass = PySequence_GetItem(args, 0); ! PyThreadState *ts = PyThreadState_GET(); ! PyTaskletObject *caller = ts->st.current; ! if (klass == NULL) ! return VALUE_ERROR("channel.send_exception(e, v...)", NULL); ! args = PySequence_GetSlice(args, 1, PySequence_Size(args)); ! if (!args) { ! goto err_exit; ! } ! result = impl_channel_send_exception_nr((PyChannelObject*)myself, klass, args); ! if (result == NULL) { ! goto err_exit; ! } else if (result == Py_UnwindToken) { ! Py_INCREF(Py_None); ! caller->tempval = Py_None; ! return result; ! } ! Py_INCREF(Py_None); ! result = Py_None; ! err_exit: ! Py_DECREF(klass); ! Py_XDECREF(args); ! return result; } *************** *** 353,365 **** goto err_exit; } ! switch (impl_channel_send_exception((PyChannelObject*)myself, klass, args)) { ! case -1: goto err_exit; ! case 1: ! { ! caller->tempval = Py_None; ! Py_INCREF(caller->tempval); ! return Py_UnwindToken; ! } } Py_INCREF(Py_None); --- 523,533 ---- goto err_exit; } ! result = impl_channel_send_exception_nr((PyChannelObject*)myself, klass, args); ! if (result == NULL) { goto err_exit; ! } else if (result == Py_UnwindToken) { ! Py_INCREF(Py_None); ! caller->tempval = Py_None; ! return result; } Py_INCREF(Py_None); *************** *** 386,389 **** --- 554,564 ---- PyObject * + PyChannel_Receive_nr(PyChannelObject *self) + { + PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; + return t->receive_nr(self); + } + + PyObject * PyChannel_Receive(PyChannelObject *self) { *************** *** 393,396 **** --- 568,650 ---- + static CHANNEL_RECEIVE_HEAD(impl_channel_receive_nr) + { + PyThreadState *ts = PyThreadState_GET(); + PyTaskletObject *sender, *receiver; + PyObject *result; + if (ts->st.main == NULL) return PyChannel_Receive_M(self); + + receiver = ts->st.current; + assert(PyTasklet_Check(receiver)); + + if (self->balance > 0) { + /* Receiving 1): there is somebody talking */ + sender = slp_channel_remove(self, 1); + sender->flags.blocked = 0; + result = sender->tempval; + sender->tempval = Py_None; + Py_INCREF(Py_None); + /* move sender to the end of runnables */ + slp_current_insert(sender); + NOTIFY_RECV(self, receiver, 0, NULL); + } + else { + /* Receiving 2): there is nobody talking */ + if (ts->st.flags.block_trap) + return RUNTIME_ERROR("this tasklet does not like to be blocked.", NULL); + if (ts->st.runcount == 1 && slp_revive_main()) + return RUNTIME_ERROR("the last runnable tasklet cannot be blocked.", NULL); + slp_current_remove(); + ts->st.flags.blocked = -1; + slp_channel_insert(self, receiver, -1); + NOTIFY_RECV(self, receiver, 1, NULL); + + /* note that we don't set tempval since the sender does it */ + switch (slp_schedule_nr_maybe(receiver, ts->st.current)) { + case -1: + return NULL; + case 1: + return Py_UnwindToken; + } + + if (slp_schedule_task(receiver, ts->st.current)) return NULL; + if (ts->st.tempval == NULL) { + /* reactivate on exception */ + if (receiver->flags.blocked) { + /* they *might* have invented code to unblock me early :-) */ + slp_channel_remove_specific(self, -1, receiver); + receiver->flags.blocked = 0; + slp_current_insert(receiver); + ts->st.current = receiver; + } + return NULL; + } + result = ts->st.tempval; + ts->st.tempval = NULL; + } + /* support for exception instances */ + if (PyObject_IsInstance(result, PyExc_Exception)) { + PyObject *type = (PyObject *) ((PyInstanceObject*)result)->in_class; + PyObject *args = PyObject_GetAttrString(result, "args"); + Py_INCREF(type); + /* special case: un-wrap a string exception */ + if (type == PyExc_Exception && args != NULL && PyTuple_Check(args) + && PyTuple_GET_SIZE(args) == 2 && PyString_Check(PyTuple_GET_ITEM(args, 0)) ) { + PyObject *t = PyTuple_GET_ITEM(args, 0); + PyObject *a = PyTuple_GET_ITEM(args, 1); + Py_INCREF(t); + Py_DECREF(type); + type = t; + Py_INCREF(a); + Py_DECREF(result); + result = a; + } + Py_XDECREF(args); + PyErr_Restore(type, result, NULL); + return NULL; + } + return result; + } + static CHANNEL_RECEIVE_HEAD(impl_channel_receive) { *************** *** 466,469 **** --- 720,728 ---- + static CHANNEL_RECEIVE_HEAD(wrap_channel_receive_nr) + { + return PyObject_CallMethod_nr((PyObject *) self, "receive", NULL); + } + static CHANNEL_RECEIVE_HEAD(wrap_channel_receive) { *************** *** 472,475 **** --- 731,740 ---- static PyObject * + channel_receive_nr(PyObject *myself) + { + return impl_channel_receive_nr((PyChannelObject*)myself); + } + + static PyObject * channel_receive(PyObject *myself) { *************** *** 479,485 **** static PyCMethodDef channel_cmethods[] = { ! CMETHOD_PUBLIC_ENTRY(PyChannel_HeapType, channel, send), ! CMETHOD_PUBLIC_ENTRY(PyChannel_HeapType, channel, send_exception), ! CMETHOD_PUBLIC_ENTRY(PyChannel_HeapType, channel, receive), {NULL} /* sentinel */ }; --- 744,750 ---- static PyCMethodDef channel_cmethods[] = { ! CMETHOD_PUBLIC_ENTRY_NR(PyChannel_HeapType, channel, send), ! CMETHOD_PUBLIC_ENTRY_NR(PyChannel_HeapType, channel, send_exception), ! CMETHOD_PUBLIC_ENTRY_NR(PyChannel_HeapType, channel, receive), {NULL} /* sentinel */ }; *************** *** 491,494 **** --- 756,763 ---- {"send_exception", (PyCFunction)channel_send_exception, METH_VARARGS, channel_send_exception__doc__}, {"receive", (PyCFunction)channel_receive, METH_NOARGS, channel_receive__doc__}, + /* special section for _nr implementations */ + {NULL, (PyCFunction)channel_send_nr, 0, "send"}, + {NULL, (PyCFunction)channel_send_exception_nr, 0, "send_exception"}, + {NULL, (PyCFunction)channel_receive_nr, 0, "receive"}, {NULL, NULL} /* sentinel */ }; Index: channelobject.h =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/channelobject.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** channelobject.h 25 Nov 2002 17:48:40 -0000 1.2 --- channelobject.h 12 Mar 2004 15:57:35 -0000 1.3 *************** *** 1,7 **** #define CHANNEL_SEND_HEAD(func) \ ! int func (PyChannelObject *self, PyObject *arg) #define CHANNEL_SEND_EXCEPTION_HEAD(func) \ ! int func (PyChannelObject *self, PyObject *klass, PyObject *args) #define CHANNEL_RECEIVE_HEAD(func) \ --- 1,7 ---- #define CHANNEL_SEND_HEAD(func) \ ! PyObject * func (PyChannelObject *self, PyObject *arg) #define CHANNEL_SEND_EXCEPTION_HEAD(func) \ ! PyObject * func (PyChannelObject *self, PyObject *klass, PyObject *args) #define CHANNEL_RECEIVE_HEAD(func) \ *************** *** 13,18 **** --- 13,21 ---- /* the fast callbacks */ CHANNEL_SEND_HEAD( (*send) ); + CHANNEL_SEND_HEAD( (*send_nr) ); CHANNEL_SEND_EXCEPTION_HEAD( (*send_exception) ); + CHANNEL_SEND_EXCEPTION_HEAD( (*send_exception_nr)); CHANNEL_RECEIVE_HEAD( (*receive) ); + CHANNEL_RECEIVE_HEAD( (*receive_nr) ); } PyChannel_HeapType; Index: scheduling.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/scheduling.c,v retrieving revision 1.80 retrieving revision 1.81 diff -C2 -d -r1.80 -r1.81 *** scheduling.c 2 Mar 2004 20:31:44 -0000 1.80 --- scheduling.c 12 Mar 2004 15:57:35 -0000 1.81 *************** *** 233,238 **** return 0; /* we can't handle escape from a channel with soft switching, yet */ ! if (next->flags.blocked) return 0; ts->st.ticker = ts->st.interval; --- 233,241 ---- return 0; /* we can't handle escape from a channel with soft switching, yet */ ! /* ! if (next->flags.blocked) { return 0; + } + */ ts->st.ticker = ts->st.interval; Index: taskletobject.c =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/taskletobject.c,v retrieving revision 1.86 retrieving revision 1.87 diff -C2 -d -r1.86 -r1.87 *** taskletobject.c 12 Mar 2004 12:05:19 -0000 1.86 --- taskletobject.c 12 Mar 2004 15:57:35 -0000 1.87 *************** *** 47,54 **** int err; #define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;} - VISIT(t->f.frame); VISIT(t->tempval); VISIT(t->cstate); return 0; } --- 47,54 ---- int err; #define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;} VISIT(t->f.frame); VISIT(t->tempval); VISIT(t->cstate); + #undef VISIT return 0; } *************** *** 144,147 **** --- 144,150 ---- /* destructing a tasklet without destroying it */ + static void + tasklet_clear(PyTaskletObject *t) + { #define ZAP(x) \ if (x != NULL) { \ *************** *** 151,157 **** } - static void - tasklet_clear(PyTaskletObject *t) - { if (t->topframe != NULL) { kill_finally(t); --- 154,157 ---- *************** *** 163,166 **** --- 163,168 ---- if (t->cstate != NULL && t->cstate->task == t) t->cstate->task = NULL; + + #undef ZAP } *************** *** 539,542 **** --- 541,545 ---- { PyThreadState *ts = PyThreadState_GET(); + PyObject *ret; assert(PyTasklet_Check(task)); if (ts->st.main == NULL) return PyTasklet_Run_M(task); *************** *** 547,553 **** if (slp_schedule_task(ts->st.current, task)) return NULL; if (ts->st.tempval == NULL) return NULL; ! Py_DECREF(ts->st.tempval); ts->st.tempval = NULL; ! return 0; } --- 550,556 ---- if (slp_schedule_task(ts->st.current, task)) return NULL; if (ts->st.tempval == NULL) return NULL; ! ret = ts->st.tempval; ts->st.tempval = NULL; ! return ret; } *************** *** 853,862 **** The tasklet is immediately activated."; ! static int PyTasklet_RaiseException_M(PyTaskletObject *self, PyObject *klass, PyObject *args) { ! PyObject *ret = PyStackless_CallMethod_Main((PyObject*)self, ! "raise_exception", "(OO)", klass, args); ! return slp_return_wrapper(ret); } --- 856,863 ---- The tasklet is immediately activated."; ! static PyObject * PyTasklet_RaiseException_M(PyTaskletObject *self, PyObject *klass, PyObject *args) { ! return PyStackless_CallMethod_Main((PyObject*)self, "raise_exception", "(OO)", klass, args); } *************** *** 864,889 **** { PyTasklet_HeapType *t = (PyTasklet_HeapType *)self->ob_type; ! return t->raise_exception(self, klass, args); } ! static TASKLET_RAISE_EXCEPTION_HEAD(impl_tasklet_raise_exception) { PyThreadState *ts = PyThreadState_GET(); PyObject *tb = NULL; if (ts->st.main == NULL) return PyTasklet_RaiseException_M(self, klass, args); if (! (PyObject_IsSubclass(klass, PyExc_Exception) == 1 || PyString_Check(klass) ) ) ! return TYPE_ERROR("tasklet.raise_exception needs Exception or string subclass as first parameter", -1); if (self->topframe == NULL) ! return RUNTIME_ERROR("You cannot raise an exception in an unbound(dead) tasklet", -1); Py_INCREF(klass); if (! PyTuple_Check(args)) { args = Py_BuildValue("(O)", args); ! if (args == NULL) return -1; } ! else Py_INCREF(args); PyErr_NormalizeException(&klass, &args, &tb); ! if (!slp_get_flags(self)->blocked && self->next != NULL) PyTasklet_Remove(self); /* XXX we should track containment in a channel and be able to remove at any time */ if (self->next == NULL) { --- 865,940 ---- { PyTasklet_HeapType *t = (PyTasklet_HeapType *)self->ob_type; ! return slp_return_wrapper(t->raise_exception_nr(self, klass, args)); } ! static TASKLET_RAISE_EXCEPTION_HEAD(impl_tasklet_raise_exception_nr) { PyThreadState *ts = PyThreadState_GET(); PyObject *tb = NULL; + PyObject *ret; if (ts->st.main == NULL) return PyTasklet_RaiseException_M(self, klass, args); if (! (PyObject_IsSubclass(klass, PyExc_Exception) == 1 || PyString_Check(klass) ) ) ! return TYPE_ERROR("tasklet.raise_exception needs Exception or string subclass as first parameter", NULL); if (self->topframe == NULL) ! return RUNTIME_ERROR("You cannot raise an exception in an unbound(dead) tasklet", NULL); Py_INCREF(klass); if (! PyTuple_Check(args)) { args = Py_BuildValue("(O)", args); ! if (args == NULL) return NULL; ! } else { ! Py_INCREF(args); } ! PyErr_NormalizeException(&klass, &args, &tb); ! if (!slp_get_flags(self)->blocked && self->next != NULL) { ! PyTasklet_Remove(self); ! } ! /* XXX we should track containment in a channel and be able to remove at any time */ ! if (self->next == NULL) { ! Py_INCREF(self); ! slp_current_insert(self); ! } ! PyErr_Restore(klass, args, tb); ! if (self->tempval != NULL) { ! Py_DECREF(self->tempval); ! self->tempval = NULL; ! } ! Py_INCREF(Py_None); ! ts->st.tempval = Py_None; ! ! switch (slp_schedule_nr_maybe(ts->st.current, self)) { ! case -1: ! return NULL; ! case 1: ! return Py_UnwindToken; ! } ! ! if (slp_schedule_task(ts->st.current, self)) return NULL; ! if (ts->st.tempval == NULL) return NULL; ! ret = ts->st.tempval; ! ts->st.tempval = NULL; ! return ret; ! } ! ! static TASKLET_RAISE_EXCEPTION_HEAD(impl_tasklet_raise_exception) ! { ! PyThreadState *ts = PyThreadState_GET(); ! PyObject *tb = NULL; ! PyObject *ret; ! if (ts->st.main == NULL) return PyTasklet_RaiseException_M(self, klass, args); ! if (! (PyObject_IsSubclass(klass, PyExc_Exception) == 1 || PyString_Check(klass) ) ) ! return TYPE_ERROR("tasklet.raise_exception needs Exception or string subclass as first parameter", NULL); ! if (self->topframe == NULL) ! return RUNTIME_ERROR("You cannot raise an exception in an unbound(dead) tasklet", NULL); ! Py_INCREF(klass); ! if (! PyTuple_Check(args)) { ! args = Py_BuildValue("(O)", args); ! if (args == NULL) return NULL; ! } else { Py_INCREF(args); + } PyErr_NormalizeException(&klass, &args, &tb); ! if (!slp_get_flags(self)->blocked && self->next != NULL) { PyTasklet_Remove(self); + } /* XXX we should track containment in a channel and be able to remove at any time */ if (self->next == NULL) { *************** *** 898,917 **** Py_INCREF(Py_None); ts->st.tempval = Py_None; ! if (slp_schedule_task(ts->st.current, self)) return -1; ! if (ts->st.tempval == NULL) return -1; ! Py_DECREF(ts->st.tempval); ts->st.tempval = NULL; ! return 0; } static TASKLET_RAISE_EXCEPTION_HEAD(wrap_tasklet_raise_exception) { ! PyObject * ret = PyObject_CallMethod((PyObject *)self, "raise_exception", "(OO)", ! klass, args); ! return slp_return_wrapper(ret); } static PyObject * ! tasklet_raise_exception(PyObject *myself, PyObject *args) { PyObject *result = NULL; --- 949,972 ---- Py_INCREF(Py_None); ts->st.tempval = Py_None; ! ! if (slp_schedule_task(ts->st.current, self)) return NULL; ! if (ts->st.tempval == NULL) return NULL; ! ret = ts->st.tempval; ts->st.tempval = NULL; ! return ret; ! } ! ! static TASKLET_RAISE_EXCEPTION_HEAD(wrap_tasklet_raise_exception_nr) ! { ! return PyObject_CallMethod_nr((PyObject *)self, "raise_exception", "(OO)", klass, args); } static TASKLET_RAISE_EXCEPTION_HEAD(wrap_tasklet_raise_exception) { ! return PyObject_CallMethod((PyObject *)self, "raise_exception", "(OO)", klass, args); } static PyObject * ! tasklet_raise_exception_nr(PyObject *myself, PyObject *args) { PyObject *result = NULL; *************** *** 920,934 **** return VALUE_ERROR("tasklet.raise_exception(e, v...)", NULL); args = PySequence_GetSlice(args, 1, PySequence_Size(args)); ! if (!args) { ! goto err_exit; ! } ! if (impl_tasklet_raise_exception((PyTaskletObject*)myself, klass, args)) ! goto err_exit; ! Py_INCREF(Py_None); ! result = Py_None; err_exit: Py_DECREF(klass); Py_XDECREF(args); return result; } --- 975,1004 ---- return VALUE_ERROR("tasklet.raise_exception(e, v...)", NULL); args = PySequence_GetSlice(args, 1, PySequence_Size(args)); ! if (!args) goto err_exit; ! result = impl_tasklet_raise_exception_nr((PyTaskletObject*)myself, klass, args); ! if (result == NULL) goto err_exit; ! return result; err_exit: Py_DECREF(klass); Py_XDECREF(args); + return NULL; + } + + static PyObject * + tasklet_raise_exception(PyObject *myself, PyObject *args) + { + PyObject *result = NULL; + PyObject *klass = PySequence_GetItem(args, 0); + if (klass == NULL) + return VALUE_ERROR("tasklet.raise_exception(e, v...)", NULL); + args = PySequence_GetSlice(args, 1, PySequence_Size(args)); + if (!args) goto err_exit; + result = impl_tasklet_raise_exception((PyTaskletObject*)myself, klass, args); + if (result == NULL) goto err_exit; return result; + err_exit: + Py_DECREF(klass); + Py_XDECREF(args); + return NULL; } *************** *** 1263,1266 **** --- 1333,1337 ---- /* special section for _nr implementations */ {NULL, (PyCFunction)tasklet_run_nr, 0, "run"}, + {NULL, (PyCFunction)tasklet_raise_exception_nr, 0, "raise_exception"}, {NULL, NULL} /* sentinel */ }; *************** *** 1274,1278 **** CMETHOD_PUBLIC_ENTRY(PyTasklet_HeapType, tasklet, become), CMETHOD_PUBLIC_ENTRY(PyTasklet_HeapType, tasklet, capture), ! CMETHOD_PUBLIC_ENTRY(PyTasklet_HeapType, tasklet, raise_exception), CMETHOD_PUBLIC_ENTRY(PyTasklet_HeapType, tasklet, kill), {NULL} /* sentinel */ --- 1345,1349 ---- CMETHOD_PUBLIC_ENTRY(PyTasklet_HeapType, tasklet, become), CMETHOD_PUBLIC_ENTRY(PyTasklet_HeapType, tasklet, capture), ! CMETHOD_PUBLIC_ENTRY_NR(PyTasklet_HeapType, tasklet, raise_exception), CMETHOD_PUBLIC_ENTRY(PyTasklet_HeapType, tasklet, kill), {NULL} /* sentinel */ Index: taskletobject.h =================================================================== RCS file: /home/cvs/slpdev/src/2.3/sprint/Stackless/taskletobject.h,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** taskletobject.h 10 Jan 2004 06:13:45 -0000 1.8 --- taskletobject.h 12 Mar 2004 15:57:35 -0000 1.9 *************** *** 21,25 **** #define TASKLET_RAISE_EXCEPTION_HEAD(func) \ ! int func (PyTaskletObject *self, PyObject *klass, PyObject *args) #define TASKLET_KILL_HEAD(func) \ --- 21,25 ---- #define TASKLET_RAISE_EXCEPTION_HEAD(func) \ ! PyObject *func (PyTaskletObject *self, PyObject *klass, PyObject *args) #define TASKLET_KILL_HEAD(func) \ *************** *** 38,41 **** --- 38,42 ---- TASKLET_CAPTURE_HEAD( (*capture) ); TASKLET_RAISE_EXCEPTION_HEAD( (*raise_exception) ); + TASKLET_RAISE_EXCEPTION_HEAD( (*raise_exception_nr) ); TASKLET_KILL_HEAD( (*kill) ); } PyTasklet_HeapType; _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins