@@ -98,7 +98,82 @@ def __repr__(self) -> str:
9898 return f"{{func={ self .func .__name__ } , _periodUs={ self ._periodUs } , expirationUs={ self .expirationUs } }}"
9999
100100
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 :
102177
103178 __slots__ = "_data"
104179
@@ -162,7 +237,7 @@ def __init__(self, period: wpimath.units.seconds = kDefaultPeriod) -> None:
162237 # All periodic functions created by addPeriodic are relative
163238 # to this self._startTimeUs
164239 self ._startTimeUs = _getFPGATime ()
165- self ._callbacks = _OrderedList ()
240+ self ._callbacks = _OrderedListSort ()
166241 self ._loopStartTimeUs = 0
167242 self .addPeriodic (self ._loopFunc , period = self ._periodS )
168243
@@ -236,19 +311,21 @@ def startCompetition(self) -> None:
236311
237312 # self._loopStartTimeUs = startTimeUs # Uncomment this line for legacy behavior.
238313
239- self ._runCallbackAtHeadOfListAndReschedule ()
314+ self ._runCallbackAtHeadOfListAndReschedule (callback )
240315
241316 # Process all other callbacks that are ready to run
242317 # Changing the comparison to be _getFPGATime() rather than
243318 # 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 )
246323 finally :
247324 # pytests hang on PC when we don't force a call to self._stopNotifier()
248325 self ._stopNotifier ()
249326
250- def _runCallbackAtHeadOfListAndReschedule (self ) -> None :
251- callback = self ._callbacks .peek ()
327+ def _runCallbackAtHeadOfListAndReschedule (self , callback ) -> None :
328+ # callback = self._callbacks.peek()
252329 # The callback.func() may have added more callbacks to self._callbacks,
253330 # but each is sorted by the _getFPGATime() at the moment it is
254331 # created, which is greater than self.expirationUs of this callback,
0 commit comments