1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
'''
This software is licensed under the GPL (GNU General Public License) version 2
as it appears here: http://www.gnu.org/copyleft/gpl.html
It is also included with this archive as `gpl.txt <gpl.txt>`_.
'''
import sched
import time
import traceback
import Queue
import sys
import os
USE_WX_TIMER = 1
class sobject(object):
__slots__ = 'sched', 'function', 'args', 'kwargs', 'delay', 'priority', 'runcount', 'item'
# an object-oriented version of the scheduler interface, with auto multi-run
def __init__(self, sched, runcount, delay, priority, function, *args, **kwargs):
## print "scheduling item with delay", delay, function
self.sched = sched
self.function = function
self.args = args
self.kwargs = kwargs
self.runcount = runcount
self.delay = delay
self.priority = priority
self.item = None
if runcount is None or runcount > 0:
self._sched(delay, priority, self.run)
def _sched(self, delay, priority, run):
self.item = GlobalSchedule.enter(delay, priority, run, ())
gsq = GlobalSchedule._queue[:1]
if USE_WX_TIMER and gsq and gsq[0] is self.item:
dt = max(int((gsq[0].time - time.time())*1000), 10)
TIMER_INSTANCE.Stop()
TIMER_INSTANCE.Start(milliseconds=dt, oneShot=True)
## print "starting timer!"
def cancel(self):
if self.runcount is None or self.runcount > 0:
if self.item:
self.sched.cancel(self.item)
self.runcount = 0
def run(self):
if self.runcount is None or self.runcount > 0:
try:
return self.function(*self.args, **self.kwargs)
finally:
if self.runcount is not None:
self.runcount -= 1
if self.runcount is None or self.runcount > 0:
self._sched(self.delay, self.priority, self.run)
def reenter(self, delay, priority, runcount=1):
self.cancel()
self.runcount = runcount
self.item = self.sched.enter(delay, self.priority, self.run, ())
#the wx-like interface
def Start(self, msdelay=-1, oneShot=False):
if msdelay == -1:
msdelay = 1000*self.delay
if not oneShot:
count = None
else:
count = 1
## print ''.join(traceback.format_stack()[-4:]).rstrip()
## print "starting", msdelay/1000.0, self.function
self.reenter(msdelay/1000.0, 0, count)
Stop = cancel
def IsRunning(self):
return self.runcount is None or self.runcount > 0
GlobalSchedule = sched.scheduler(time.time, (lambda arg:None), True)
GlobalQ = Queue.Queue()
CyclesPerSecond = 40
QUIT = 0
def PFutureCall(msdelay, priority, function, *args, **kwargs):
return sobject(GlobalSchedule, 1, msdelay/1000.0, priority, function, *args, **kwargs)
def FutureCall(msdelay, function, *args, **kwargs):
return PFutureCall(msdelay, 0, function, *args, **kwargs)
def ShutdownScheduler():
global QUIT
QUIT = 1
def runme(*args, **kwargs):
os._exit(0)
PFutureCall(-1000000, -1000000, runme)
def Timer(function, *args, **kwargs):
# We'll "schedule" it to run zero times after 1 second
return sobject(GlobalSchedule, 0, 1, 0, function, *args, **kwargs)
def actually_run():
global cancelled
try:
cancelled
except NameError:
cancelled = sys.modules['__main__'].cancelled
for i in GlobalQ.get():
if QUIT:
break
_1, _2, fcn, arg = i
try:
## print "running function...", fcn
fcn(*arg)
except cancelled:
pass
except (SystemExit, AssertionError, KeyboardInterrupt):
break
except:
import traceback
traceback.print_exc()
def RunScheduledEvents():
x = GlobalSchedule.getqueue(time.time(), copy=0)
if QUIT:
return 1
import wx
GlobalQ.put(x)
if QUIT:
return 1
try:
wx.CallAfter(actually_run)
except AssertionError:
return 1
return 0
def _schedulethread(ok=0):
while ok and not QUIT:
time.sleep(1.0/max(CyclesPerSecond, 1))
if QUIT:
return
if RunScheduledEvents():
return
if QUIT:
return
import threading
x = threading.Thread(target=_schedulethread, args=(1,))
x.setDaemon(1)
x.start()
import sys
sys.modules['__builtin__'].FutureCall = FutureCall
sys.modules['__builtin__'].PFutureCall = FutureCall
sys.modules['__builtin__'].Timer = Timer
sys.modules['__builtin__'].ShutdownScheduler = ShutdownScheduler
if USE_WX_TIMER:
def OnTimerDone(evt=None):
## print "going to run scheduled events..."
TIMER_INSTANCE.Stop()
if RunScheduledEvents():
## print "need to kill the scheduler..."
return
gsq = GlobalSchedule._queue[:1]
dt = 1000
if gsq:
## print "event:", gsq[0]
dt = min(max(int((gsq[0].time - time.time())*1000), 10), 1000)
TIMER_INSTANCE.Start(milliseconds=dt, oneShot=True)
## print "starting timer!"
def _schedulethread(ok=0):
global wx, WXAPP, TIMER_INSTANCE
import wx
WXAPP = wx.GetApp()
TIMER_INSTANCE = wx.Timer(WXAPP, wx.NewId())
WXAPP.Bind(wx.EVT_TIMER, OnTimerDone, TIMER_INSTANCE)
TIMER_INSTANCE.Start(1, oneShot=True)
## print "starting timer!"
|