On 5 Sep 2005 07:27:41 -0700, "Paul McGuire" <pt***@austin.r r.com> wrote:
I still think there are savings to be had by looping inside the
try-except block, which avoids many setup/teardown exception handling
steps. This is not so pretty in another way (repeated while on
check()), but I would be interested in your timings w.r.t. your current
code.
def loop(self):
self_pool_pople ft = self.pool.pople ft
self_pool_appen d = self.pool.appen d
self_call_exit_ funcs = self.call_exit_ funcs
check = self.pool.__len __
while check() > 0:
try:
while check() > 0:
task = self_pool_pople ft()
task.next()
self_pool_appen d(task)
except StopIteration:
self_call_exit_ funcs(task)
Why not let popleft trigger an exception out of while True instead,
and prevent tasks from raising StopIteration, and let them yield a None
to indicate keep scheduling with no special action, and something else
for optional differentiation of various exit options, e.g., zero for die,
and nonzero for suspension waiting for event(s) E.g., a returned integer
could be an event mask or single index (+ vs -) for thing(s) to wait for.
If you work things right, event check in the loop can be an if like
if waitedfor&event s: process_events( ), which most of the time is a fast no-op).
Then (without event stuff, and untested ;-) maybe something like:
def loop(self):
self_pool_pople ft = self.pool.pople ft
self_pool_appen d = self.pool.appen d
self_call_exit_ funcs = self.call_exit_ funcs
try:
while True:
task = self_pool_pople ft()
if task.next() is None:
self_call_exit_ funcs(task)
else:
self_pool_appen d(task)
except Indexerror:
pass
You could even consider putting the bound task.next methods in
the deque instead of the task, and using deque rotation instead
of popping and appending. Then, if you put the task.next's in
reverse order in the deque to start with, self_pool[-1] will be
the first, and self_pool_rotat e() will bring the next into position.
Which would make it look like (untested!):
def loop(self):
self_pool_pop = self.pool.pop
self_call_exit_ funcs = self.call_exit_ funcs
self_pool_rotat e = self.pool.rotat e
try:
while True:
if self.pool[-1]() is None:
self_call_exit_ funcs(self_pool _pop())
else:
self_pool_rotat e()
except Indexerror:
pass
IWT if the pool remains unchanged most of the time, pool_rotate() ought
to be faster than popping and appending. Note that exit_funcs will need
a mapping of task.next -> task most likely, unless communication is
entirely via a mutable task state object, and all that's needed is to
me map to that and mess with exit state there and trigger a final .next()
to wrap up the generator.
Regards,
Bengt Richter