nzbToMedia/libs/jaraco/windows/timers.py

70 lines
1.8 KiB
Python

# -*- coding: UTF-8 -*-
"""
timers
In particular, contains a waitable timer.
"""
from __future__ import absolute_import
import time
from six.moves import _thread
from jaraco.windows.api import event as win32event
__author__ = 'Jason R. Coombs <jaraco@jaraco.com>'
class WaitableTimer:
"""
t = WaitableTimer()
t.set(None, 10) # every 10 seconds
t.wait_for_signal() # 10 seconds elapses
t.stop()
t.wait_for_signal(20) # 20 seconds elapses (timeout occurred)
"""
def __init__(self):
self.signal_event = win32event.CreateEvent(None, 0, 0, None)
self.stop_event = win32event.CreateEvent(None, 0, 0, None)
def set(self, due_time, period):
_thread.start_new_thread(self._signal_loop, (due_time, period))
def stop(self):
win32event.SetEvent(self.stop_event)
def wait_for_signal(self, timeout = None):
"""
wait for the signal; return after the signal has occurred or the
timeout in seconds elapses.
"""
timeout_ms = int(timeout*1000) if timeout else win32event.INFINITE
win32event.WaitForSingleObject(self.signal_event, timeout_ms)
def _signal_loop(self, due_time, period):
if not due_time and not period:
raise ValueError("due_time or period must be non-zero")
try:
if not due_time:
due_time = time.time() + period
if due_time:
self._wait(due_time - time.time())
while period:
due_time += period
self._wait(due_time - time.time())
except Exception:
pass
#we're done here, just quit
def _wait(self, seconds):
milliseconds = int(seconds*1000)
if milliseconds > 0:
res = win32event.WaitForSingleObject(self.stop_event, milliseconds)
if res == win32event.WAIT_OBJECT_0: raise Exception
if res == win32event.WAIT_TIMEOUT: pass
win32event.SetEvent(self.signal_event)
@staticmethod
def get_even_due_time(period):
now = time.time()
return now - (now % period)