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

  1. /*
  2. BROKER MODULE
  3. Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #pragma once
  6. #include <functional>
  7. #include <utility>
  8. #include <vector>
  9. #include <tuple>
  10. // Example usage:
  11. //
  12. // module.h
  13. // BrokerDeclare(CustomBroker, void(int));
  14. //
  15. // module.cpp
  16. // BrokerBind(CustomBroker);
  17. //
  18. // other.cpp
  19. // #include "module.h"
  20. // void func() {
  21. // CustomBroker::Register([](int arg) { Serial.println(arg); }
  22. // CustomBroker::Publish(12345);
  23. // }
  24. template <typename Func>
  25. struct TBroker {};
  26. template <typename R, typename ...Args>
  27. struct TBroker<R(Args...)> {
  28. using TArgs = typename std::tuple<Args...>;
  29. using TCallback = std::function<R(Args...)>;
  30. using TCallbacks = std::vector<TCallback>;
  31. TBroker(const TBroker&) = delete;
  32. TBroker& operator=(const TBroker&) = delete;
  33. TBroker() = default;
  34. // TODO: https://source.chromium.org/chromium/chromium/src/+/master:base/callback_list.h
  35. // Consider giving out 'subscription' / 'token', so that the caller can remove callback later
  36. void Register(TCallback callback) {
  37. callbacks.push_back(callback);
  38. }
  39. void Publish(Args... args) {
  40. for (auto& callback : callbacks) {
  41. callback(args...);
  42. }
  43. }
  44. protected:
  45. TCallbacks callbacks;
  46. };
  47. // TODO: since 1.14.0 we intoduced static syntax for Brokers, ::Register & ::Publish.
  48. // Preserve it (up to a point) when creating module-level objects.
  49. // Provide a helper namespace with Register & Publish, instance and
  50. // To help out VS Code with argument discovery, put TArgs as the first template parameter.
  51. #define BrokerDeclare(Name, Signature) \
  52. namespace Name { \
  53. using type = TBroker<Signature>; \
  54. extern type Instance; \
  55. template<typename S = type::TArgs, typename ...Args> \
  56. inline void Register(Args&&... args) { \
  57. Instance.Register(std::forward<Args>(args)...); \
  58. }\
  59. \
  60. template<typename S = type::TArgs, typename ...Args> \
  61. inline void Publish(Args&&... args) { \
  62. Instance.Publish(std::forward<Args>(args)...); \
  63. }\
  64. }
  65. #define BrokerBind(Name) \
  66. namespace Name { \
  67. Name::type Instance; \
  68. }