]> code.delx.au - bg-scripts/blob - asyncsched.py
Automated merge with ssh://hg@kagami.tsukasa.net.au/bg_scripts/
[bg-scripts] / asyncsched.py
1 # Copyright 2008 James Bunton <jamesbunton@fastmail.fm>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
3 # asyncore.loop() with delayed function calls
4
5 import asyncore
6 import heapq
7 import signal
8 import time
9
10 tasks = []
11 running = False
12
13 class Task(object):
14 def __init__(self, delay, func, args=[], kwargs={}):
15 self.time = time.time() + delay
16 self.func = lambda: func(*args, **kwargs)
17
18 def __cmp__(self, other):
19 return cmp(self.time, other.time)
20
21 def __call__(self):
22 f = self.func
23 self.func = None
24 if f:
25 return f()
26
27 def cancel(self):
28 assert self.func is not None
29 self.func = None
30
31 def schedule(delay, func, args=[], kwargs={}):
32 task = Task(delay, func, args, kwargs)
33 heapq.heappush(tasks, task)
34 return task
35
36 def loop(timeout=30.0, use_poll=False):
37 global running
38 running = True
39 oldhandler = signal.signal(signal.SIGTERM, exit)
40
41 while running:
42 now = time.time()
43 while tasks and tasks[0].time < now:
44 task = heapq.heappop(tasks)
45 task()
46
47 t = timeout
48 if tasks:
49 t = max(min(t, tasks[0].time - now), 0)
50
51 asyncore.loop(timeout=t, count=1, use_poll=use_poll)
52
53 signal.signal(signal.SIGTERM, oldhandler)
54
55 def exit(*args):
56 global running
57 running = False
58
59 __all__ = ("schedule", "loop", "exit")
60