summaryrefslogtreecommitdiffstats
path: root/Lib/sched.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/sched.py')
-rw-r--r--Lib/sched.py45
1 files changed, 31 insertions, 14 deletions
diff --git a/Lib/sched.py b/Lib/sched.py
index 1643236..f0da829 100644
--- a/Lib/sched.py
+++ b/Lib/sched.py
@@ -16,11 +16,11 @@ integers or floating point numbers, as long as it is consistent.
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 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
+event means calling the action function, passing it the argument
+sequence in "argument" (remember that in Python, multiple function
+arguments are be packed in a sequence).
+The action function may be an instance method so it
has another way to reference private data (besides global variables).
-Parameterless functions or methods cannot be used, however.
"""
# XXX The timefunc and delayfunc should have been defined as methods
@@ -29,14 +29,17 @@ Parameterless functions or methods cannot be used, however.
# XXX the global state of your particular time and delay functions.
import heapq
+from collections import namedtuple
__all__ = ["scheduler"]
+Event = namedtuple('Event', 'time, priority, action, argument')
+
class scheduler:
def __init__(self, timefunc, delayfunc):
"""Initialize a new instance, passing the time and delay
functions"""
- self.queue = []
+ self._queue = []
self.timefunc = timefunc
self.delayfunc = delayfunc
@@ -47,8 +50,8 @@ class scheduler:
if necessary.
"""
- event = time, priority, action, argument
- heapq.heappush(self.queue, event)
+ event = Event(time, priority, action, argument)
+ heapq.heappush(self._queue, event)
return event # The ID
def enter(self, delay, priority, action, argument):
@@ -64,15 +67,15 @@ class scheduler:
"""Remove an event from the queue.
This must be presented the ID as returned by enter().
- If the event is not in the queue, this raises RuntimeError.
+ If the event is not in the queue, this raises ValueError.
"""
- self.queue.remove(event)
- heapq.heapify(self.queue)
+ self._queue.remove(event)
+ heapq.heapify(self._queue)
def empty(self):
"""Check whether the queue is empty."""
- return not self.queue
+ return not self._queue
def run(self):
"""Execute events until the queue is empty.
@@ -89,7 +92,7 @@ class scheduler:
exceptions are not caught but the scheduler's state remains
well-defined so run() may be called again.
- A questionably hack is added to allow other threads to run:
+ A questionable hack is added to allow other threads to run:
just after an event is executed, a delay of 0 is executed, to
avoid monopolizing the CPU when other threads are also
runnable.
@@ -97,7 +100,7 @@ class scheduler:
"""
# localize variable access to minimize overhead
# and to improve thread safety
- q = self.queue
+ q = self._queue
delayfunc = self.delayfunc
timefunc = self.timefunc
pop = heapq.heappop
@@ -111,7 +114,21 @@ class scheduler:
# 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)
+ action(*argument)
delayfunc(0) # Let other threads run
else:
heapq.heappush(q, event)
+
+ @property
+ def queue(self):
+ """An ordered list of upcoming events.
+
+ Events are named tuples with fields for:
+ time, priority, action, arguments
+
+ """
+ # Use heapq to sort the queue rather than using 'sorted(self._queue)'.
+ # With heapq, two events scheduled at the same time will show in
+ # the actual order they would be retrieved.
+ events = self._queue[:]
+ return map(heapq.heappop, [events]*len(events))