Repository navigation
✨ (minor) v6: Add can_interrupt_dispatcher - #111
Merged
Merged
Conversation
kammce
force-pushed
the
v6-edge-triggered-multiplexer
branch
from
October 14, 2026 22:03
d1b62ad to
7f68f87
Compare
kammce
force-pushed
the
v6-can-interrupt-multiplexer
branch
from
October 14, 2026 22:03
5567d82 to
c5bbe68
Compare
kammce
force-pushed
the
v6-edge-triggered-multiplexer
branch
from
October 14, 2026 23:50
7f68f87 to
251186c
Compare
kammce
force-pushed
the
v6-can-interrupt-multiplexer
branch
from
October 14, 2026 23:50
c5bbe68 to
a024694
Compare
kammce
force-pushed
the
v6-edge-triggered-multiplexer
branch
from
October 15, 2026 02:44
251186c to
79d0dbd
Compare
kammce
force-pushed
the
v6-can-interrupt-multiplexer
branch
from
October 15, 2026 02:44
a024694 to
37c0ca3
Compare
kammce
force-pushed
the
v6-edge-triggered-multiplexer
branch
from
October 15, 2026 05:38
79d0dbd to
dc6c906
Compare
kammce
force-pushed
the
v6-can-interrupt-multiplexer
branch
from
October 15, 2026 05:38
37c0ca3 to
5642c09
Compare
kammce
force-pushed
the
v6-edge-triggered-multiplexer
branch
from
October 17, 2026 01:26
dc6c906 to
e5ecd8e
Compare
kammce
force-pushed
the
v6-can-interrupt-multiplexer
branch
from
October 17, 2026 03:02
5642c09 to
08184be
Compare
hal::can_interrupt accepts one subscriber at a time. The dispatcher subscribes once to a real CAN receive interrupt and provides N slots. Each slot is a full can_interrupt with its own subscriber and an optional hal::can_dispatch_filter, which matches a message when its ID format (standard or extended) matches and (id & mask) == (filter.id & mask). A slot without a filter receives every message. Messages reach each matching subscriber in slot order, in interrupt context. A slot's filter can only change while it has no subscriber, so the interrupt never reads a half-written filter. operator[] is lifetimebound and deleted on a temporary dispatcher, the dispatcher cannot outlive its interrupt, and its subscription is its last member so it is removed before the slots are destroyed. Compile checks cover the same misuse as the edge-triggered dispatcher.
kammce
force-pushed
the
v6-can-interrupt-multiplexer
branch
from
October 17, 2026 14:44
08184be to
e56eed2
Compare
libhal's can_interrupt::on_receive() now takes a hal::can_receive_filter (libhal/libhal#252), so each subscriber passes the filter for the IDs it handles. A slot stores the filter its subscriber passed, and the dispatcher subscribes to the real interrupt for every message. - Drops can_dispatch_filter and slot::allow()/filter(); libhal's can_receive_filter replaces them. It compares IDs only, so one filter works for standard and extended messages. - A compiler fence keeps the filter written before the callback that makes the slot live, since the interrupt reads them in that order. - Requires libhal >= 5.0.0-alpha.5.
kammce
commented
Oct 22, 2026
Move the nested slot out of can_interrupt_dispatcher<N> into hal::can_interrupt_slot, so dispatchers of different sizes no longer instantiate their own slot class and vtable. Use static_cast<void>() instead of a C-style void cast in the tests.
Only a dispatcher creates slots, so user code cannot make one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #109. Depends on libhal/libhal#252, which adds
hal::can_receive_filtertocan_interrupt::on_receive(). This PR's CI needslibhal/5.0.0-alpha.5, which #252 cuts when it merges.hal::can_interrupt_dispatcher<N>lets several subscribers share onehal::can_interrupt, which in libhal v5 accepts a single subscriber. Each subscriber passes its own filter when it subscribes, the same as with a real interrupt, so whoever wires up the dispatcher doesn't need to know any driver's IDs.Behavior
hal::can_interruptwith one subscriber. A second subscriber throwshal::subscription_busy.hal::can_interrupt_slot, sodispatcher<2>anddispatcher<7>don't each instantiate their own slot class and vtable. Its constructor is private: only a dispatcher creates slots.hal::can_receive_filterits subscriber passed toon_receive(). The filter is{ id, mask }from libhal.(message.id & mask) == (id & mask). It compares IDs only, so one filter works for standard and extended messages.std::atomic_signal_fence) keeps the filter written before the callback that makes the slot live, since the interrupt reads them in that order. It emits no instructions and isn'tstd::atomic.edge_triggered_interrupt_dispatcher(✨ v6: Add edge_triggered_interrupt_dispatcher #110):operator[], withoperator[]deleted on a temporary;Tests
tests/can.test.cpp:subscription_busyon a taken interrupt;out_of_range;Testing
macOS, LLVM 23, against libhal built locally from libhal/libhal#252 (as
libhal/latest, viareplace_requires): all 16 test suites pass, and both compile-check files pass.