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
|
import threading
import time
current_time = 0.0
subscriber_lock = threading.Lock()
update_lock = threading.Lock()
thread_should_exit = False
thread_alive = False
class Subscription:
def __init__(self, interval: float, id: int):
self.interval = interval
self.id = id
subscribers = []
def get_interval(max_interval: float):
if subscribers:
return min(sub.interval for sub in subscribers)
return max_interval
def timing_thread():
global current_time, thread_should_exit
while not thread_should_exit:
interval = get_interval(1.0)
acquired = update_lock.acquire(timeout=interval)
if acquired:
update_lock.release()
current_time = time.perf_counter()
def pyi_timing_thread_subscribe(desired_interval: float):
global thread_alive, thread_should_exit, current_time
with subscriber_lock:
if not thread_alive:
update_lock.acquire()
thread_should_exit = False
threading.Thread(target=timing_thread).start()
thread_alive = True
current_time = time.perf_counter()
ids = [sub.id for sub in subscribers]
new_id = 0
while new_id in ids:
new_id += 1
subscribers.append(Subscription(desired_interval, new_id))
update_lock.release()
update_lock.acquire()
return new_id
def pyi_timing_thread_unsubscribe(id: int):
with subscriber_lock:
subscriber_to_remove = next((sub for sub in subscribers if sub.id == id), None)
if subscriber_to_remove:
subscribers.remove(subscriber_to_remove)
if not subscribers:
global thread_should_exit, thread_alive
thread_should_exit = True
update_lock.release()
thread_alive = False
return 0
else:
raise Exception("PYI_TIMING_THREAD_NOT_SUBSCRIBED")
def pyi_timing_thread_get_time() -> float:
return current_time
def pyi_timing_thread_get_interval() -> float:
return get_interval(float("inf")) if thread_alive else -1.0
|