@@ -98,7 +98,82 @@ def __repr__(self) -> str:
98
98
return f"{{func={ self .func .__name__ } , _periodUs={ self ._periodUs } , expirationUs={ self .expirationUs } }}"
99
99
100
100
101
- class _OrderedList :
101
+ class _OrderedListSort :
102
+
103
+ __slots__ = "_data"
104
+
105
+ def __init__ (self ) -> None :
106
+ self ._data : list [Any ] = []
107
+
108
+ def add (self , item : Any ) -> None :
109
+ self ._data .append (item )
110
+ self ._data .sort ()
111
+
112
+ def pop (self ) -> Any :
113
+ return self ._data .pop ()
114
+
115
+ def peek (
116
+ self ,
117
+ ) -> Any : # todo change to Any | None when we don't build with python 3.9
118
+ if self ._data :
119
+ return self ._data [0 ]
120
+ else :
121
+ return None
122
+
123
+ def reorderListAfterAChangeInTheFirstElement (self ):
124
+ self ._data .sort ()
125
+
126
+ def __len__ (self ) -> int :
127
+ return len (self ._data )
128
+
129
+ def __iter__ (self ) -> Iterable [Any ]:
130
+ return iter (sorted (self ._data ))
131
+
132
+ def __contains__ (self , item ) -> bool :
133
+ return item in self ._data
134
+
135
+ def __repr__ (self ) -> str :
136
+ return str (sorted (self ._data ))
137
+
138
+
139
+ class _OrderedListMin :
140
+
141
+ __slots__ = "_data"
142
+
143
+ def __init__ (self ) -> None :
144
+ self ._data : list [Any ] = []
145
+
146
+ def add (self , item : Any ) -> None :
147
+ self ._data .append (item )
148
+
149
+ # def pop(self) -> Any:
150
+ # return self._data.pop()
151
+
152
+ def peek (
153
+ self ,
154
+ ) -> Any : # todo change to Any | None when we don't build with python 3.9
155
+ if self ._data :
156
+ return min (self ._data )
157
+ else :
158
+ return None
159
+
160
+ def reorderListAfterAChangeInTheFirstElement (self ):
161
+ pass
162
+
163
+ def __len__ (self ) -> int :
164
+ return len (self ._data )
165
+
166
+ def __iter__ (self ) -> Iterable [Any ]:
167
+ return iter (sorted (self ._data ))
168
+
169
+ def __contains__ (self , item ) -> bool :
170
+ return item in self ._data
171
+
172
+ def __repr__ (self ) -> str :
173
+ return str (sorted (self ._data ))
174
+
175
+
176
+ class _OrderedListHeapq :
102
177
103
178
__slots__ = "_data"
104
179
@@ -162,7 +237,7 @@ def __init__(self, period: wpimath.units.seconds = kDefaultPeriod) -> None:
162
237
# All periodic functions created by addPeriodic are relative
163
238
# to this self._startTimeUs
164
239
self ._startTimeUs = _getFPGATime ()
165
- self ._callbacks = _OrderedList ()
240
+ self ._callbacks = _OrderedListSort ()
166
241
self ._loopStartTimeUs = 0
167
242
self .addPeriodic (self ._loopFunc , period = self ._periodS )
168
243
@@ -236,19 +311,21 @@ def startCompetition(self) -> None:
236
311
237
312
# self._loopStartTimeUs = startTimeUs # Uncomment this line for legacy behavior.
238
313
239
- self ._runCallbackAtHeadOfListAndReschedule ()
314
+ self ._runCallbackAtHeadOfListAndReschedule (callback )
240
315
241
316
# Process all other callbacks that are ready to run
242
317
# Changing the comparison to be _getFPGATime() rather than
243
318
# self._loopStartTimeUs would also be correct.
244
- while self ._callbacks .peek ().expirationUs <= self ._loopStartTimeUs :
245
- self ._runCallbackAtHeadOfListAndReschedule ()
319
+ while (
320
+ callback := self ._callbacks .peek ()
321
+ ).expirationUs <= _getFPGATime ():
322
+ self ._runCallbackAtHeadOfListAndReschedule (callback )
246
323
finally :
247
324
# pytests hang on PC when we don't force a call to self._stopNotifier()
248
325
self ._stopNotifier ()
249
326
250
- def _runCallbackAtHeadOfListAndReschedule (self ) -> None :
251
- callback = self ._callbacks .peek ()
327
+ def _runCallbackAtHeadOfListAndReschedule (self , callback ) -> None :
328
+ # callback = self._callbacks.peek()
252
329
# The callback.func() may have added more callbacks to self._callbacks,
253
330
# but each is sorted by the _getFPGATime() at the moment it is
254
331
# created, which is greater than self.expirationUs of this callback,
0 commit comments