def testTimeoutAbsMono(): def test1(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print(testnum, arguments['delay']) arguments['test'] = True ED2.breakLoop() def test2(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print(testnum, arguments['delay']) arguments['test'] = 'bar' ED2.breakLoop() mt = MonoTime() arguments = {'test': False, 'delay': None} timeout_1 = TimeoutAbsMono(test1, mt, arguments, 'test1', mt) ED2.loop() assert (arguments['test']) assert (arguments['delay'] < 0.1) mt1 = mt.getOffsetCopy(0.1) mt2 = mt.getOffsetCopy(0.2) arguments = {'test': False, 'delay': None} timeout_1 = TimeoutAbsMono(test1, mt1, arguments, 'test2', mt1) timeout_2 = TimeoutAbsMono(test2, mt2, arguments, 'test3', mt2) timeout_1.cancel() ED2.loop() assert (arguments['test'] == 'bar') assert (arguments['delay'] < 0.1)
def testTimeoutAbsMono(): def test1(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print(testnum, arguments['delay']) arguments['test'] = True ED2.breakLoop() def test2(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print(testnum, arguments['delay']) arguments['test'] = 'bar' ED2.breakLoop() mt = MonoTime() arguments = {'test':False, 'delay':None} timeout_1 = TimeoutAbsMono(test1, mt, arguments, 'test1', mt) ED2.loop() assert(arguments['test']) assert(arguments['delay'] < 0.1) mt1 = mt.getOffsetCopy(0.1) mt2 = mt.getOffsetCopy(0.2) arguments = {'test':False, 'delay':None} timeout_1 = TimeoutAbsMono(test1, mt1, arguments, 'test2', mt1) timeout_2 = TimeoutAbsMono(test2, mt2, arguments, 'test3', mt2) timeout_1.cancel() ED2.loop() assert(arguments['test'] == 'bar') assert(arguments['delay'] < 0.1)
class EventDispatcher2(Singleton): tlisteners = None slisteners = None endloop = False signals_pending = None twasted = 0 tcbs_lock = None last_ts = None my_ident = None state_lock = Lock() ed_inum = 0 elp = None bands = None def __init__(self, freq = 100.0): EventDispatcher2.state_lock.acquire() if EventDispatcher2.ed_inum != 0: EventDispatcher2.state_lock.release() raise StdException('BZZZT, EventDispatcher2 has to be singleton!') EventDispatcher2.ed_inum = 1 EventDispatcher2.state_lock.release() self.tcbs_lock = Lock() self.tlisteners = [] self.slisteners = [] self.signals_pending = [] self.last_ts = MonoTime() self.my_ident = get_ident() self.elp = ElPeriodic(freq) self.elp.CFT_enable(signal.SIGURG) self.bands = [(freq, 0),] def signal(self, signum, frame): self.signals_pending.append(signum) def regTimer(self, timeout_cb, ival, nticks = 1, abs_time = False, *cb_params): self.last_ts = MonoTime() if nticks == 0: return if abs_time and not isinstance(ival, MonoTime): raise TypeError('ival is not MonoTime') el = EventListener() el.itime = self.last_ts.getCopy() el.cb_func = timeout_cb el.ival = ival el.nticks = nticks el.abs_time = abs_time el.cb_params = cb_params el.ed = self return el def dispatchTimers(self): while len(self.tlisteners) != 0: el = self.tlisteners[0] if el.cb_func != None and el.etime > self.last_ts: # We've finished return el = heappop(self.tlisteners) if el.cb_func == None: # Skip any already removed timers self.twasted -= 1 continue if el.nticks == -1 or el.nticks > 1: # Re-schedule periodic timer if el.nticks > 1: el.nticks -= 1 if el.randomize_runs != None: ival = el.randomize_runs(el.ival) else: ival = el.ival el.etime.offset(ival) heappush(self.tlisteners, el) cleanup = False else: cleanup = True try: if not el.cb_with_ts: el.cb_func(*el.cb_params) else: el.cb_func(self.last_ts, *el.cb_params) except Exception as ex: if isinstance(ex, SystemExit): raise dump_exception('EventDispatcher2: unhandled exception when processing timeout event') if self.endloop: return if cleanup: el.cleanup() def regSignal(self, signum, signal_cb, *cb_params, **cb_kw_args): sl = EventListener() if len([x for x in self.slisteners if x.signum == signum]) == 0: signal.signal(signum, self.signal) sl.signum = signum sl.cb_func = signal_cb sl.cb_params = cb_params sl.cb_kw_args = cb_kw_args self.slisteners.append(sl) return sl def unregSignal(self, sl): self.slisteners.remove(sl) if len([x for x in self.slisteners if x.signum == sl.signum]) == 0: signal.signal(sl.signum, signal.SIG_DFL) sl.cleanup() def dispatchSignals(self): while len(self.signals_pending) > 0: signum = self.signals_pending.pop(0) for sl in [x for x in self.slisteners if x.signum == signum]: if sl not in self.slisteners: continue try: sl.cb_func(*sl.cb_params, **sl.cb_kw_args) except Exception as ex: if isinstance(ex, SystemExit): raise dump_exception('EventDispatcher2: unhandled exception when processing signal event') if self.endloop: return def dispatchThreadCallback(self, thread_cb, cb_params): try: thread_cb(*cb_params) except Exception as ex: if isinstance(ex, SystemExit): raise dump_exception('EventDispatcher2: unhandled exception when processing from-thread-call') #print('dispatchThreadCallback dispatched', thread_cb, cb_params) def callFromThread(self, thread_cb, *cb_params): self.elp.call_from_thread(self.dispatchThreadCallback, thread_cb, cb_params) #print('EventDispatcher2.callFromThread completed', str(self), thread_cb, cb_params) def loop(self, timeout = None, freq = None): if freq != None and self.bands[0][0] != freq: for fb in self.bands: if fb[0] == freq: self.bands.remove(fb) break else: fb = (freq, self.elp.addband(freq)) self.elp.useband(fb[1]) self.bands.insert(0, fb) self.endloop = False self.last_ts = MonoTime() if timeout != None: etime = self.last_ts.getOffsetCopy(timeout) while True: if len(self.signals_pending) > 0: self.dispatchSignals() if self.endloop: return if self.endloop: return self.dispatchTimers() if self.endloop: return if self.twasted * 2 > len(self.tlisteners): # Clean-up removed timers when their share becomes more than 50% self.tlisteners = [x for x in self.tlisteners if x.cb_func != None] heapify(self.tlisteners) self.twasted = 0 if (timeout != None and self.last_ts > etime) or self.endloop: self.endloop = False break self.elp.procrastinate() self.last_ts = MonoTime() def breakLoop(self): self.endloop = True
from twisted.internet import reactor from sippy.Time.MonoTime import MonoTime def test1(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print testnum, arguments['delay'] arguments['test'] = True reactor.crash() def test2(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print testnum, arguments['delay'] arguments['test'] = 'bar' reactor.crash() mt = MonoTime() arguments = {'test':False, 'delay':None} timeout_1 = TimeoutAbsMono(test1, mt, arguments, 'test1', mt) reactor.run() assert(arguments['test']) assert(arguments['delay'] < 0.1) mt1 = mt.getOffsetCopy(0.1) mt2 = mt.getOffsetCopy(0.2) arguments = {'test':False, 'delay':None} timeout_1 = TimeoutAbsMono(test1, mt1, arguments, 'test2', mt1) timeout_2 = TimeoutAbsMono(test2, mt2, arguments, 'test3', mt2) timeout_1.cancel() reactor.run() assert(arguments['test'] == 'bar') assert(arguments['delay'] < 0.1)
from twisted.internet import reactor from sippy.Time.MonoTime import MonoTime def test1(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print testnum, arguments['delay'] arguments['test'] = True reactor.crash() def test2(arguments, testnum, mtm): arguments['delay'] = mtm.offsetFromNow() print testnum, arguments['delay'] arguments['test'] = 'bar' reactor.crash() mt = MonoTime() arguments = {'test': False, 'delay': None} timeout_1 = TimeoutAbsMono(test1, mt, arguments, 'test1', mt) reactor.run() assert (arguments['test']) assert (arguments['delay'] < 0.1) mt1 = mt.getOffsetCopy(0.1) mt2 = mt.getOffsetCopy(0.2) arguments = {'test': False, 'delay': None} timeout_1 = TimeoutAbsMono(test1, mt1, arguments, 'test2', mt1) timeout_2 = TimeoutAbsMono(test2, mt2, arguments, 'test3', mt2) timeout_1.cancel() reactor.run() assert (arguments['test'] == 'bar') assert (arguments['delay'] < 0.1)