From 253b163f3bba57f40ad485e0ea2d27b95ab95bf2 Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Fri, 30 Aug 2024 15:20:07 -0600 Subject: [PATCH] :bug: Fix handler short-circuiting The handler should call all the callbacks that match a message, not just the first that matches. This is consistent with the indexed_handler behaviour. NOTE: The order of calling the callbacks is not defined. --- include/msg/handler.hpp | 6 ++++-- test/msg/handler.cpp | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/include/msg/handler.hpp b/include/msg/handler.hpp index d587982a..2a86ec95 100644 --- a/include/msg/handler.hpp +++ b/include/msg/handler.hpp @@ -21,8 +21,10 @@ struct handler : handler_interface { auto handle(BaseMsg const &msg, ExtraCallbackArgs... args) const -> bool final { - bool const found_valid_callback = stdx::any_of( - [&](auto &callback) { return callback.handle(msg, args...); }, + auto const found_valid_callback = stdx::apply( + [&](auto &...cbs) -> bool { + return (0u | ... | cbs.handle(msg, args...)); + }, callbacks); if (!found_valid_callback) { CIB_ERROR("None of the registered callbacks claimed this message:"); diff --git a/test/msg/handler.cpp b/test/msg/handler.cpp index b4a07b06..95e5533b 100644 --- a/test/msg/handler.cpp +++ b/test/msg/handler.cpp @@ -93,7 +93,7 @@ TEST_CASE("log mismatch when no match", "[handler]") { TEST_CASE("match and dispatch only one callback", "[handler]") { auto callback1 = msg::callback<"cb1", msg_defn>( - id_match<0x80>, [&](msg::const_view) { CHECK(false); }); + id_match<0x80>, [](msg::const_view) { CHECK(false); }); auto callback2 = msg::callback<"cb2", msg_defn>( id_match<0x44>, [](msg::const_view) { dispatched = true; }); auto const msg = std::array{0x4400ba11u, 0x0042d00du}; @@ -107,6 +107,25 @@ TEST_CASE("match and dispatch only one callback", "[handler]") { CHECK(dispatched); } +TEST_CASE("dispatch all callbacks that match", "[handler]") { + int count{}; + + auto callback1 = msg::callback<"cb1", msg_defn>( + id_match<0x80>, [](msg::const_view) { CHECK(false); }); + auto callback2 = msg::callback<"cb2", msg_defn>( + id_match<0x44>, [&](msg::const_view) { ++count; }); + auto callback3 = msg::callback<"cb3", msg_defn>( + id_match<0x44>, [&](msg::const_view) { ++count; }); + auto const msg = std::array{0x4400ba11u, 0x0042d00du}; + + auto callbacks = stdx::make_tuple(callback1, callback2, callback3); + static auto handler = + msg::handler{callbacks}; + + CHECK(handler.handle(msg)); + CHECK(count == 2); +} + namespace { template using uint8_view =