From: Ken H. <ke...@ha...> - 2007-02-22 19:29:04
|
It seems that there is no way to kill a Task from the outside. The only way to prematurely end a running task is to have the task's function (loop) check some flag and 'return' instead of 'yield'. For simple tasks this is easy but in some cases (multiple yield points) it could be complex. Can/Should we add support to kill a Task? For example: mytask = tasks.Task(my_func()) ... mytask.die() What about also adding a wait() function so that the main task can wait for the task to end (synchronize)? |
From: Thomas L. <ta...@gm...> - 2007-02-23 20:34:25
|
On Thu, 22 Feb 2007 11:29:22 -0800, Ken Hayber wrote: > It seems that there is no way to kill a Task from the outside. The only > way to prematurely end a running task is to have the task's function > (loop) check some flag and 'return' instead of 'yield'. For simple > tasks this is easy but in some cases (multiple yield points) it could be > complex. > > Can/Should we add support to kill a Task? > > For example: > > mytask = tasks.Task(my_func()) > ... > mytask.die() Python 2.5 allows throwing exceptions into a generator, which is probably the best way of doing it (once 2.5 is the base platform). > What about also adding a wait() function so that the main task can wait > for the task to end (synchronize)? Yes, I think every task should itself be (or contain) a Blocker so you can do that. -- Dr Thomas Leonard http://rox.sourceforge.net GPG: 9242 9807 C985 3C07 44A6 8B9A AE07 8280 59A5 3CC1 |
From: Ken H. <ke...@ha...> - 2007-02-27 23:32:24
|
Thomas Leonard wrote: > On Thu, 22 Feb 2007 11:29:22 -0800, Ken Hayber wrote: > >> It seems that there is no way to kill a Task from the outside. The only >> way to prematurely end a running task is to have the task's function >> (loop) check some flag and 'return' instead of 'yield'. For simple >> tasks this is easy but in some cases (multiple yield points) it could be >> complex. >> >> Can/Should we add support to kill a Task? >> >> For example: >> >> mytask = tasks.Task(my_func()) >> ... >> mytask.die() > > Python 2.5 allows throwing exceptions into a generator, which is probably > the best way of doing it (once 2.5 is the base platform). Well for now this seems to work. class Task: ... def die(self): # Remove from our blockers' queues for blocker in self._rox_blockers: blocker.remove_task(self) ... Except that you tend to get KeyError exceptions because the task may already have ended. I guess that the handling of this exception should be in the calling app, not the library? IOW, should it be an exception to kill a task that already ended, or should we quietly ignore it? >> What about also adding a wait() function so that the main task can wait >> for the task to end (synchronize)? > > Yes, I think every task should itself be (or contain) a Blocker so you can > do that. Do you have a method to do this in mind? I understand the concept, but how do you make the main loop/task wait on a Blocker? |
From: Thomas L. <ta...@gm...> - 2007-03-03 11:57:57
|
On 2/27/07, Ken Hayber <ke...@ha...> wrote: > IOW, should it be an exception to kill a task that already ended, or should we > quietly ignore it? Depends. Why do you want to kill it? If the task is well behaved then you can always do: def my_task(kill_request): yield [normal_blockers, kill_request] if kill_request.happened: return ... kill_rq = Blocker() t = Task(my_task(kill_rq)) kill_rq.trigger() > >> What about also adding a wait() function so that the main task can wait > >> for the task to end (synchronize)? > > > > Yes, I think every task should itself be (or contain) a Blocker so you can > > do that. > > Do you have a method to do this in mind? I understand the concept, but > how do you make the main loop/task wait on a Blocker? I've added a 'finished' attribute now, so you can do: t = Task(...) yield t.finished print "t has finished" Of course, you have to make sure that your 'main' task is itself a Task, otherwise you can't yield, but I don't think that's a big problem. -- Dr Thomas Leonard http://rox.sourceforge.net GPG: 9242 9807 C985 3C07 44A6 8B9A AE07 8280 59A5 3CC1 |
From: Ken H. <ke...@ha...> - 2007-03-04 03:42:43
|
Resending. sf.net is suddenly rejecting my emails... Ken Hayber wrote: > Thomas Leonard wrote: >> On 2/27/07, Ken Hayber <ke...@ha...> wrote: >>> IOW, should it be an exception to kill a task that already ended, or >>> should we >>> quietly ignore it? >> >> Depends. Why do you want to kill it? If the task is well behaved then >> you can always do: >> >> def my_task(kill_request): >> yield [normal_blockers, kill_request] >> if kill_request.happened: return >> ... >> >> kill_rq = Blocker() >> t = Task(my_task(kill_rq)) >> kill_rq.trigger() > > Your 'if kill_request.happened: return' doesn't fit my use case. I > would need to put this statement at several points in 'my_task' to > handle all the cases I want to exit from. For a simple task that is > easy as you showed. > >>>>> What about also adding a wait() function so that the main task can >>>>> wait >>>>> for the task to end (synchronize)? >>>> Yes, I think every task should itself be (or contain) a Blocker so >>>> you can >>>> do that. >>> Do you have a method to do this in mind? I understand the concept, but >>> how do you make the main loop/task wait on a Blocker? >> >> I've added a 'finished' attribute now, so you can do: >> >> t = Task(...) >> yield t.finished >> print "t has finished" >> >> Of course, you have to make sure that your 'main' task is itself a >> Task, otherwise you can't yield, but I don't think that's a big >> problem. > > ??? I don't see it. How does this work? > > |