[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
Bob Ippolito
bob at centera.de
Fri Mar 12 16:57:38 CET 2004
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
More information about the Stackless-checkins
mailing list