/* BROKER MODULE Copyright (C) 2017-2019 by Xose PĂ©rez */ #pragma once #include #include #include #include // Example usage: // // module.h // BrokerDeclare(CustomBroker, void(int)); // // module.cpp // BrokerBind(CustomBroker); // // other.cpp // #include "module.h" // void func() { // CustomBroker::Register([](int arg) { Serial.println(arg); } // CustomBroker::Publish(12345); // } template struct TBroker {}; template struct TBroker { using TArgs = typename std::tuple; using TCallback = std::function; using TCallbacks = std::vector; TBroker(const TBroker&) = delete; TBroker& operator=(const TBroker&) = delete; TBroker() = default; // TODO: https://source.chromium.org/chromium/chromium/src/+/master:base/callback_list.h // Consider giving out 'subscription' / 'token', so that the caller can remove callback later void Register(TCallback callback) { callbacks.push_back(callback); } void Publish(Args... args) { for (auto& callback : callbacks) { callback(args...); } } protected: TCallbacks callbacks; }; // TODO: since 1.14.0 we intoduced static syntax for Brokers, ::Register & ::Publish. // Preserve it (up to a point) when creating module-level objects. // Provide a helper namespace with Register & Publish, instance and // To help out VS Code with argument discovery, put TArgs as the first template parameter. #define BrokerDeclare(Name, Signature) \ namespace Name { \ using type = TBroker; \ extern type Instance; \ template \ inline void Register(Args&&... args) { \ Instance.Register(std::forward(args)...); \ }\ \ template \ inline void Publish(Args&&... args) { \ Instance.Publish(std::forward(args)...); \ }\ } #define BrokerBind(Name) \ namespace Name { \ Name::type Instance; \ }