[Python-checkins] python/dist/src/Lib sched.py,1.14,1.15

rhettinger at users.sourceforge.net rhettinger at users.sourceforge.net
Fri Dec 17 14:52:23 CET 2004


Update of /cvsroot/python/python/dist/src/Lib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6436
Modified Files:
	sched.py 
Log Message:
Refactor:
* Improve algorithm -- no more O(n) steps except sched.cancel().
* Improve thread safety of sched.run() and sched.empty()
 (other threads could alter the queue between the time the queue was
 first checked and when the lead event was deleted).
* Localize variable access in sched.run() to minimize overhead.
Index: sched.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/sched.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- sched.py	27 Feb 2003 20:14:41 -0000	1.14
+++ sched.py	17 Dec 2004 13:52:20 -0000	1.15
@@ -15,7 +15,7 @@
 
 Events are specified by tuples (time, priority, action, argument).
 As in UNIX, lower priority numbers mean higher priority; in this
-way the queue can be maintained fully sorted. Execution of the
+way the queue can be maintained as a priority queue. Execution of the
 event means calling the action function, passing it the argument.
 Remember that in Python, multiple function arguments can be packed
 in a tuple. The action function may be an instance method so it
@@ -28,7 +28,7 @@
 # XXX instead of having to define a module or class just to hold
 # XXX the global state of your particular time and delay functions.
 
-import bisect
+import heapq
 
 __all__ = ["scheduler"]
 
@@ -48,7 +48,7 @@
 
 """
 event = time, priority, action, argument
- bisect.insort(self.queue, event)
+ heapq.heappush(self.queue, event)
 return event # The ID
 
 def enter(self, delay, priority, action, argument):
@@ -68,10 +68,11 @@
 
 """
 self.queue.remove(event)
+ heapq.heapify(self.queue)
 
 def empty(self):
 """Check whether the queue is empty."""
- return len(self.queue) == 0
+ return not not self.queue
 
 def run(self):
 """Execute events until the queue is empty.
@@ -94,13 +95,23 @@
 runnable.
 
 """
+ # localize variable access to minimize overhead
+ # and to improve thread safety
 q = self.queue
+ delayfunc = self.delayfunc
+ timefunc = self.timefunc
+ pop = heapq.heappop
 while q:
- time, priority, action, argument = q[0]
- now = self.timefunc()
+ time, priority, action, argument = checked_event = q[0]
+ now = timefunc()
 if now < time:
- self.delayfunc(time - now)
+ delayfunc(time - now)
 else:
- del q[0]
- void = action(*argument)
- self.delayfunc(0) # Let other threads run
+ event = pop(q)
+ # Verify that the event was not removed or altered
+ # by another thread after we last looked at q[0].
+ if event is checked_event:
+ void = action(*argument)
+ delayfunc(0) # Let other threads run
+ else:
+ heapq.heappush(event)


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /