buttons: Fix possible ordering issue if a callback blocks
Invoke button callbacks directly from the background thread. This ensures that button notifications are delivered and delivered in the correct order. Previously, if a callback blocked, it was possible a new update could start before the previous update was completed, which could lead to lost events or out of order events. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
25bc649cd2
commit
92fe8f15b8
|
@ -1,6 +1,6 @@
|
||||||
# Support for button detection and callbacks
|
# Support for button detection and callbacks
|
||||||
#
|
#
|
||||||
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2018-2023 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
import logging
|
import logging
|
||||||
|
@ -69,17 +69,17 @@ class MCU_buttons:
|
||||||
# Send ack to MCU
|
# Send ack to MCU
|
||||||
self.ack_cmd.send([self.oid, new_count])
|
self.ack_cmd.send([self.oid, new_count])
|
||||||
self.ack_count += new_count
|
self.ack_count += new_count
|
||||||
# Call self.handle_button() with this event in main thread
|
# Invoke callbacks with this event in main thread
|
||||||
for nb in new_buttons:
|
btime = params['#receive_time']
|
||||||
self.reactor.register_async_callback(
|
for button in new_buttons:
|
||||||
(lambda e, s=self, b=nb: s.handle_button(e, b)))
|
|
||||||
def handle_button(self, eventtime, button):
|
|
||||||
button ^= self.invert
|
button ^= self.invert
|
||||||
changed = button ^ self.last_button
|
changed = button ^ self.last_button
|
||||||
|
self.last_button = button
|
||||||
for mask, shift, callback in self.callbacks:
|
for mask, shift, callback in self.callbacks:
|
||||||
if changed & mask:
|
if changed & mask:
|
||||||
callback(eventtime, (button & mask) >> shift)
|
state = (button & mask) >> shift
|
||||||
self.last_button = button
|
self.reactor.register_async_callback(
|
||||||
|
(lambda et, c=callback, bt=btime, s=state: c(bt, s)))
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
Loading…
Reference in New Issue