|
|
- /*
-
- BROKER MODULE
-
- Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
-
- */
-
- #pragma once
-
- #include <functional>
- #include <utility>
- #include <vector>
- #include <tuple>
-
- // 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 <typename Func>
- struct TBroker {};
-
- template <typename R, typename ...Args>
- struct TBroker<R(Args...)> {
-
- using TArgs = typename std::tuple<Args...>;
- using TCallback = std::function<R(Args...)>;
- using TCallbacks = std::vector<TCallback>;
-
- 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<Signature>; \
- extern type Instance; \
- template<typename S = type::TArgs, typename ...Args> \
- inline void Register(Args&&... args) { \
- Instance.Register(std::forward<Args>(args)...); \
- }\
- \
- template<typename S = type::TArgs, typename ...Args> \
- inline void Publish(Args&&... args) { \
- Instance.Publish(std::forward<Args>(args)...); \
- }\
- }
-
- #define BrokerBind(Name) \
- namespace Name { \
- Name::type Instance; \
- }
-
|