Always use poll
[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, select
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 __lt__(self, other):
19 return self.time < other.time
20
21 def __eq__(self, other):
22 return self.time == other.time
23
24 def __call__(self):
25 f = self.func
26 self.func = None
27 if f:
28 return f()
29
30 def cancel(self):
31 assert self.func is not None
32 self.func = None
33
34 def schedule(delay, func, args=[], kwargs={}):
35 task = Task(delay, func, args, kwargs)
36 heapq.heappush(tasks, task)
37 return task
38
39 def loop(timeout=30.0, use_poll=False):
40 global running
41 running = True
42 oldhandler = signal.signal(signal.SIGTERM, exit)
43
44 while running:
45 now = time.time()
46 while tasks and tasks[0].time < now:
47 task = heapq.heappop(tasks)
48 task()
49
50 t = timeout
51 if tasks:
52 t = max(min(t, tasks[0].time - now), 0)
53
54 asyncore.poll2(timeout=t)
55
56 signal.signal(signal.SIGTERM, oldhandler)
57
58 def exit(*args):
59 global running
60 running = False
61
62 __all__ = ("schedule", "loop", "exit")
63