Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

89 lines
2.1 KiB

/*
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; \
}