[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