-
Notifications
You must be signed in to change notification settings - Fork 9
/
timed_event_handler.py
116 lines (95 loc) · 3.64 KB
/
timed_event_handler.py
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
#!/usr/bin/env python
# Copyright (c) 2018 Christoph Pilz
#
# This work is licensed under the terms of the MIT license.
# For a copy, see <https://opensource.org/licenses/MIT>.
import time
from threading import Barrier, Lock
from threading import BrokenBarrierError
from support.singleton import Singleton
from support.util import TimeStamp
class TimedEventHandler(metaclass=Singleton):
def __init__(self):
self.__currentSimTime = None
self.__previousSimTime = None
self.__events = None
self.__subscribers = {}
self.__syncBarrier = Barrier(1) # (1): Simulator Control Blocks too
self.__syncLock = Lock()
self.__isStarted = False
self.__cleared = True
def cleanup(self):
self.__syncLock.acquire()
self.__syncLock.release()
def clear(self):
self.__init__()
def getCurrentSimTime(self):
self.__syncLock.acquire()
simtime = self.__currentSimTime
self.__syncLock.release()
return simtime
def getCurrentSimTimeStamp(self):
self.__syncLock.acquire()
simtime = self.__currentSimTime
self.__syncLock.release()
timestamp = TimeStamp(int(simtime), (simtime - int(simtime))*1000000)
return timestamp
def getPreviousSimTimeStamp(self):
self.__syncLock.acquire()
simtime = self.__previousSimTime
self.__syncLock.release()
timestamp = TimeStamp(int(simtime), (simtime - int(simtime))*1000000)
return timestamp
def getSimTimeDiff(self):
self.__syncLock.acquire()
if self.__previousSimTime is None:
timeDiff = None
else:
timeDiff = self.__currentSimTime - self.__previousSimTime
self.__syncLock.release()
return timeDiff
def updateSimStep(self, newSimTime):
self.__syncLock.acquire()
self.__previousSimTime = self.__currentSimTime
self.__currentSimTime = newSimTime.platform_timestamp
self.__notify()
self.__syncLock.release()
def start(self):
self.__syncLock.acquire()
self.__isStarted = True
self.__syncLock.release()
def stop(self):
self.__syncLock.acquire()
self.__syncBarrier.abort()
self.__notify()
self.__syncLock.release()
def subscribe(self, name, updateMethod):
self.__syncLock.acquire()
if self.__syncBarrier.n_waiting != 0:
raise Exception(name, "tried to subscribe during runtime (syncBarrier has", self.__syncBarrier.n_waiting, "threads waiting)")
if name in self.__subscribers:
raise Exception(name, "already subscribed")
else:
self.__syncBarrier = Barrier(self.__syncBarrier.parties + 1)
self.__subscribers[name] = updateMethod
self.__syncLock.release()
def syncBarrier(self):
self.__syncLock.acquire()
started = self.__isStarted
self.__syncLock.release()
if self.__isStarted:
self.__syncBarrier.wait(timeout=1.0)
else:
pass
def unsubscribe(self, name):
self.__syncLock.acquire()
if self.__syncBarrier.n_waiting != 0 and not self.__syncBarrier.broken:
raise Exception(name, "tried to unsubscribe during runtime (syncBarrier has", self.__syncBarrier.n_waiting, "threads waiting)")
del self.__subscribers[name]
self.__syncBarrier = Barrier(self.__syncBarrier.parties - 1)
self.__syncLock.release()
def __notify(self):
for subscriber, method in self.__subscribers.items():
# check events for subscriber
event = None
method(event)