Skip to content

Commit 9b71587

Browse files
committed
Improve comments, siftup rather than pop and add.
Signed-off-by: spiresFrc9106 <[email protected]>
1 parent 0f33e68 commit 9b71587

File tree

1 file changed

+39
-8
lines changed

1 file changed

+39
-8
lines changed

subprojects/robotpy-wpilib/wpilib/timedrobotpy.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Any, Callable, Iterable, ClassVar
2-
from heapq import heappush, heappop
2+
from heapq import heappush, heappop, _siftup
33
from hal import (
44
report,
55
initializeNotifier,
@@ -24,6 +24,9 @@
2424

2525

2626
class _Callback:
27+
28+
__slots__ = "func", "_periodUs", "expirationUs"
29+
2730
def __init__(
2831
self,
2932
func: Callable[[], None],
@@ -96,6 +99,9 @@ def __repr__(self) -> str:
9699

97100

98101
class _OrderedList:
102+
103+
__slots__ = "_data"
104+
99105
def __init__(self) -> None:
100106
self._data: list[Any] = []
101107

@@ -113,6 +119,9 @@ def peek(
113119
else:
114120
return None
115121

122+
def siftupRoot(self):
123+
_siftup(self._data, 0)
124+
116125
def __len__(self) -> int:
117126
return len(self._data)
118127

@@ -189,13 +198,20 @@ def startCompetition(self) -> None:
189198
# We don't have to check there's an element in the queue first because
190199
# there's always at least one (the constructor adds one). It's re-enqueued
191200
# at the end of the loop.
192-
callback = self._callbacks.pop()
201+
callback = self._callbacks.peek()
193202

194203
status = updateNotifierAlarm(self._notifier, callback.expirationUs)
195204
if status != 0:
196205
raise RuntimeError(f"updateNotifierAlarm() returned {status}")
197206

198207
self._loopStartTimeUs, status = waitForNotifierAlarm(self._notifier)
208+
209+
# The C++ code that this was based upon used the following line to establish
210+
# the loopStart time. Uncomment it and
211+
# the "self._loopStartTimeUs = startTimeUs" further below to emulate the
212+
# legacy behavior.
213+
# startTimeUs = _getFPGATime() # uncomment this for legacy behavior
214+
199215
if status != 0:
200216
raise RuntimeError(
201217
f"waitForNotifierAlarm() returned _loopStartTimeUs={self._loopStartTimeUs} status={status}"
@@ -207,11 +223,24 @@ def startCompetition(self) -> None:
207223
# See the API for waitForNotifierAlarm
208224
break
209225

226+
# On a RoboRio 2, the following print statement results in values like:
227+
# print(f"expUs={callback.expirationUs} current={self._loopStartTimeUs}, legacy={startTimeUs}")
228+
# [2.27] expUs=3418017 current=3418078, legacy=3418152
229+
# [2.29] expUs=3438017 current=3438075, legacy=3438149
230+
# This indicates that there is about 60 microseconds of skid from
231+
# callback.expirationUs to self._loopStartTimeUs
232+
# and there is about 70 microseconds of skid from self._loopStartTimeUs to startTimeUs.
233+
# Consequently, this code uses "self._loopStartTimeUs, status = waitForNotifierAlarm"
234+
# to establish loopStartTime, rather than slowing down the code by adding an extra call to
235+
# "startTimeUs = _getFPGATime()".
236+
237+
# self._loopStartTimeUs = startTimeUs # Uncomment this line for legacy behavior.
238+
210239
self._runCallbackAndReschedule(callback)
211240

212241
# Process all other callbacks that are ready to run
213242
while self._callbacks.peek().expirationUs <= self._loopStartTimeUs:
214-
callback = self._callbacks.pop()
243+
callback = self._callbacks.peek()
215244
self._runCallbackAndReschedule(callback)
216245
finally:
217246
# pytests hang on PC when we don't force a call to self._stopNotifier()
@@ -224,7 +253,8 @@ def _runCallbackAndReschedule(self, callback: _Callback) -> None:
224253
# that ran long we immediately push the next invocation to the
225254
# following period.
226255
callback.setNextStartTimeUs(_getFPGATime())
227-
self._callbacks.add(callback)
256+
# assert callback is self._callbacks.peek()
257+
self._callbacks.siftupRoot()
228258

229259
def _stopNotifier(self):
230260
stopNotifier(self._notifier)
@@ -269,8 +299,9 @@ def addPeriodic(
269299
to TimedRobotPy.
270300
"""
271301

272-
self._callbacks.add(
273-
_Callback.makeCallBack(
274-
callback, self._startTimeUs, int(period * 1e6), int(offset * 1e6)
275-
)
302+
cb = _Callback.makeCallBack(
303+
callback, self._startTimeUs, int(period * 1e6), int(offset * 1e6)
276304
)
305+
if len(self._callbacks):
306+
assert cb > self._callbacks.peek()
307+
self._callbacks.add(cb)

0 commit comments

Comments
 (0)