timerstuff.py (4979B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\util\timerstuff.py 2 import functools 3 import logging 4 import sys 5 import traceback 6 import weakref 7 import blue 8 import ccpProfile 9 import stackless 10 import uthread 11 from carbon.common.lib import const 12 log = logging.getLogger(__name__) 13 ClockThis = sys.ClockThis 14 ClockThisWithoutTheStars = sys.ClockThisWithoutTheStars 15 16 def TimeThis(timer): 17 18 def Helper(func): 19 20 @functools.wraps(func) 21 def Wrapper(*args, **kwds): 22 t = ccpProfile.PushTimer(timer) 23 try: 24 return func(*args, **kwds) 25 finally: 26 ccpProfile.PopTimer(t) 27 28 return Wrapper 29 30 return Helper 31 32 33 class SimpleTimingContext(object): 34 35 def __enter__(self): 36 c = stackless.getcurrent() 37 self.t = (c.GetWallclockTime(), c.GetRunTime()) 38 39 def __exit__(self, exc_type, exc_value, exc_tb): 40 a, b = self.t 41 c = stackless.getcurrent() 42 self.t = (c.GetWallclockTime() - a, c.GetRunTime() - b) 43 44 def GetWallclockTime(self): 45 return self.t[0] 46 47 def GetRunTime(self): 48 return self.t[1] 49 50 51 class TimerObject: 52 53 def __init__(self, useSimTime = False): 54 self.abort = 0 55 self.id = 0 56 self.aborts = {} 57 if useSimTime: 58 self.GetTime = blue.os.GetSimTime 59 self.Sleep = blue.pyos.synchro.SleepSim 60 else: 61 self.GetTime = blue.os.GetWallclockTime 62 self.Sleep = blue.pyos.synchro.SleepWallclock 63 64 def __del__(self): 65 self.abort = 1 66 67 def DelayedCall(self, func, time, *args, **kw): 68 self.id += 1 69 callID = self.id 70 if time - self.GetTime() > const.DAY * 2: 71 raise RuntimeError('Cannot sleep for more than 48 hours') 72 uthread.new(self.DelayedCall_thread, callID, func, time, args, kw, stackless_tracing_enabled=False) 73 return callID 74 75 def DelayedCall_thread(self, callID, func, time, args, kw): 76 delay = (time - self.GetTime()) / 10000 77 if delay > 0: 78 self.Sleep(delay) 79 if callID in self.aborts: 80 del self.aborts[callID] 81 elif not self.abort: 82 try: 83 func(*args, **kw) 84 except: 85 log.exception('Error in delayed call') 86 87 def KillDelayedCall(self, id): 88 self.aborts[id] = None 89 90 def KillAllDelayedCalls(self): 91 self.abort = 1 92 93 94 def OnTimerResync(old, new): 95 diff = new - old 96 for timer in AutoTimer.autoTimers.keys(): 97 timer.wakeupAt += diff / 10000 98 99 100 class AutoTimer(object): 101 autoTimers = weakref.WeakKeyDictionary() 102 __resync_handler_registered = False 103 104 def __init__(self, interval, method, *args, **kw): 105 if interval <= 0: 106 raise RuntimeError('Invalid interval for AutoTimer') 107 if not self.__resync_handler_registered: 108 blue.pyos.synchro.timesyncs.append(OnTimerResync) 109 self.__resync_handler_registered = True 110 self.run = 1 111 self.interval = interval 112 self.method, self.args, self.kw = method, args, kw 113 caller_tb = traceback.extract_stack(limit=2)[0:1] 114 caller = traceback.format_list(caller_tb)[0].replace('\n', '') 115 methrepr = getattr(method, '__name__', '(no __name__)').replace('<', '<').replace('>', '>') 116 ctx = 'AutoTimer::(%s) on %s' % (caller, methrepr) 117 self.wakeupAt = blue.os.GetWallclockTime() / 10000 + self.interval 118 AutoTimer.autoTimers[self] = None 119 uthread.pool(ctx, AutoTimer.Loop, weakref.ref(self), stackless_tracing_enabled=False) 120 121 def KillTimer(self): 122 self.run = 0 123 124 def Reset(self, newInterval = None): 125 if newInterval is not None: 126 if newInterval <= 0: 127 raise RuntimeError('Invalid interval for AutoTimer') 128 self.interval = newInterval 129 self.wakeupAt = blue.os.GetWallclockTime() / 10000 + self.interval 130 131 def Loop(weakSelf): 132 self = weakSelf() 133 if not self or not self.run: 134 return 135 nap = self.interval 136 del self 137 while True: 138 blue.pyos.synchro.SleepWallclock(nap) 139 self = weakSelf() 140 if not self or not self.run: 141 return 142 now = blue.os.GetWallclockTime() / 10000 143 if now < self.wakeupAt: 144 nap = self.wakeupAt - now 145 else: 146 self.method(*self.args, **self.kw) 147 n = (now - self.wakeupAt) / self.interval 148 self.wakeupAt += (n + 1) * self.interval 149 nap = self.wakeupAt - now 150 del self 151 152 Loop = staticmethod(Loop) 153 154 155 class Stopwatch: 156 157 def __init__(self): 158 self.started = blue.os.GetCycles()[0] 159 160 def __str__(self): 161 return '%.3f' % ((blue.os.GetCycles()[0] - self.started) / float(blue.os.GetCycles()[1])) 162 163 def Reset(self): 164 self.started = blue.os.GetCycles()[0]