Adding an ack parameter to both set and cancel is cleaner than adding
all the set alarm parameters to the ack function. It also provides an
ack-and-cancel method.
It was possible for the alarm to fire between the set alarm and ack,
resulting in a hang on next wait. It's not possible to ack before set
alarm due to a race in sim step timing, so the fix is to provide an
atomic ack and set alarm; the easiest way to implement this in the API
was to change ack to optionally also set the alarm again.
This changes the HAL notifier interface to:
- Use wpiutil signal objects. This means waiting is done through the
`WPI_WaitObject` API instead of a dedicated function and allows for
higher level code to simultaneously wait on notifiers and other events.
- Interval timers are supported at the HAL layer
- Handlers are now required to acknowledge notifications. This is
invisible to users unless they're directly using the HAL API.
- For interval timers, an overrun count is maintained to detect if the
handler didn't acknowledge
The underlying implementation still uses condition variables for the
actual waiting. In basic testing using this approach seemed to be lower
jitter than timerfd.
Currently, the simulation and systemcore implementations are nearly
identical except for a few additional sim hook bits. This could be
refactored, but keeping them separate may make sense to keep the
systemcore implementation easy to read and reason about, or if we ever
choose to use a different underlying timer implementation on systemcore.
The simulation side API is unchanged in form but does change in
function--waiting for notifiers now only waits for currently running (or
newly signaled) notifiers to acknowledge. To avoid a race condition in
sim stepTiming, users of the low level API must make any alarm updates
(especially for one-shot alarms) prior to acknowledging the previous
alarm.
The only current use of the interval timer feature is the `Notifier`
class. The `TimedRobot` implementation still uses a single notifier and
its own interval timing logic to ensure consistent callback order. Using
separate notifiers for each user-level interval would substantially
increase complexity. `Watchdog` also doesn't use the interval timer, as
it's looking for an amount of time since the last `set` call rather than
a recurring interval time.
To reduce flicker, the sim GUI uses a fade out when a timeout goes from
set to unset.
This fixes tsan for wpilib and commands, and also fixes some spurious
test failures.