$darkmode
data_broker.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
43 #pragma once
44 #ifndef CLOE_DATA_BROKER_HPP_
45 #define CLOE_DATA_BROKER_HPP_
46 
47 #include <any>
48 #include <cassert>
49 #include <functional>
50 #include <map>
51 #include <memory>
52 #include <regex>
53 #include <stdexcept>
54 #include <string_view>
55 #include <typeindex>
56 #include <vector>
57 
58 #include <fmt/format.h>
59 
60 #include <sol/sol.hpp>
61 
62 namespace cloe {
63 
64 namespace databroker {
65 
66 namespace detail {
67 
71 template <typename T, typename = void>
72 struct has_to_lua : std::false_type {};
76 template <typename T>
77 struct has_to_lua<
78  T, std::void_t<decltype(to_lua(std::declval<sol::state_view>(), std::declval<T*>()))>>
79  : std::true_type {};
83 template <typename T>
85 
89 template <typename T>
90 void to_lua(sol::state_view lua) {
91  if constexpr (has_to_lua_v<T>) {
92  to_lua(lua, static_cast<T*>(nullptr));
93  } else {
94  // nop
95  }
96 }
97 
98 } // namespace detail
99 
105 template <typename T, bool condition>
107  using type = T;
108 };
109 
110 template <typename T>
111 struct type_t_or_int_if<T, false> {
112  using type = int;
113 };
114 
119 template <typename T>
120 constexpr bool is_incompatible_type_v = std::is_void_v<T> || std::is_reference_v<T>;
121 
131 template <typename T>
133 
137 template <typename T>
139 
143 template <typename T>
145 
153 template <typename... TArgs>
154 class Event {
155  public:
156  using EventHandler = std::function<void(TArgs...)>;
157 
158  private:
159  std::vector<EventHandler> eventhandlers_{};
160 
161  public:
165  void add(EventHandler handler) { eventhandlers_.emplace_back(std::move(handler)); }
166 
170  [[nodiscard]] std::size_t count() const { return eventhandlers_.size(); }
171 
176  void raise(TArgs&&... args) const {
177  for (const auto& eventhandler : eventhandlers_) {
178  try {
179  eventhandler(std::forward<decltype(args)>(args)...);
180  } catch (...) {
181  throw;
182  }
183  }
184  }
185 };
186 
187 } // namespace databroker
188 
189 // Forward declarations:
190 template <typename T>
191 class BasicContainer;
192 class Signal;
193 class DataBroker;
194 
198 template <typename T>
199 constexpr void assert_static_type() {
200  static_assert(!static_cast<bool>(databroker::is_incompatible_type_v<T>),
201  "Incompatible-Datatype-Error.\n"
202  "\n"
203  "Please find the offending LOC in above line 'require from here'.\n"
204  "\n"
205  "Explanation/Reasoning:\n"
206  "- references & void are fundamentally incompatible");
207 }
208 
209 using SignalPtr = std::shared_ptr<Signal>;
210 
215  std::function<void(const SignalPtr&, sol::state_view, std::string_view)>;
216 
220 using lua_signal_declarator_t = std::function<void(sol::state_view)>;
221 
222 template <typename T>
224 
225 template <typename T>
227  public:
228  using value_type = databroker::compatible_base_t<T>;
229 
230  private:
234  struct access_token {
235  explicit access_token(int /*unused*/){};
236  };
237 
238  value_type value_{};
240  Signal* signal_{};
241 
242  public:
243  BasicContainer() = default;
244  BasicContainer(Signal* signal,
246  on_value_changed,
247  access_token /*unused*/)
248  : value_(), on_value_changed_(std::move(on_value_changed)), signal_(signal) {
249  update_accessor_functions(this);
250  }
251  BasicContainer(const BasicContainer&) = delete;
252  BasicContainer(BasicContainer<value_type>&& source) { *this = std::move(source); }
253 
254  ~BasicContainer() { update_accessor_functions(nullptr); }
255  BasicContainer& operator=(const BasicContainer&) = delete;
256  BasicContainer& operator=(BasicContainer&& rhs) {
257  value_ = std::move(rhs.value_);
258  on_value_changed_ = std::move(rhs.on_value_changed_);
259  signal_ = std::move(rhs.signal_);
260  update_accessor_functions(this);
261 
262  rhs.signal_ = nullptr;
263 
264  return *this;
265  }
267  value_ = value;
268  if (on_value_changed_) {
269  on_value_changed_(value_);
270  }
271  return *this;
272  }
273 
274  const value_type& value() const { return value_; }
275  value_type& value() { return value_; }
276  void set_value(databroker::signal_type_cref_t<T> value) { *this = value; }
277 
278  [[nodiscard]] bool has_subscriber() const;
279  [[nodiscard]] std::size_t subscriber_count() const;
280 
281  // mimic std::optional
282  constexpr const value_type* operator->() const noexcept { return &value_; }
283  constexpr value_type* operator->() noexcept { return &value_; }
284  constexpr const value_type& operator*() const noexcept { return value_; }
285  constexpr value_type& operator*() noexcept { return value_; }
286 
287  private:
288  void update_accessor_functions(BasicContainer* container);
289 
290  friend class Signal;
291 };
292 
293 // Compare two BasicContainer
294 
295 template <typename T, typename U>
296 constexpr bool operator==(const BasicContainer<T>& lhs, const BasicContainer<U>& rhs) {
297  return *lhs == *rhs;
298 }
299 template <typename T, typename U>
300 constexpr bool operator!=(const BasicContainer<T>& lhs, const BasicContainer<U>& rhs) {
301  return *lhs != *rhs;
302 }
303 template <typename T, typename U>
304 constexpr bool operator<(const BasicContainer<T>& lhs, const BasicContainer<U>& rhs) {
305  return *lhs < *rhs;
306 }
307 template <typename T, typename U>
308 constexpr bool operator<=(const BasicContainer<T>& lhs, const BasicContainer<U>& rhs) {
309  return *lhs <= *rhs;
310 }
311 template <typename T, typename U>
312 constexpr bool operator>(const BasicContainer<T>& lhs, const BasicContainer<U>& rhs) {
313  return *lhs > *rhs;
314 }
315 template <typename T, typename U>
316 constexpr bool operator>=(const BasicContainer<T>& lhs, const BasicContainer<U>& rhs) {
317  return *lhs >= *rhs;
318 }
319 
320 // Compare BasicContainer with a value
321 
322 template <typename T, typename U>
323 constexpr bool operator==(const BasicContainer<T>& lhs, const U& rhs) {
324  return *lhs == rhs;
325 }
326 template <typename T, typename U>
327 constexpr bool operator==(const T& lhs, const BasicContainer<U>& rhs) {
328  return lhs == *rhs;
329 }
330 template <typename T, typename U>
331 constexpr bool operator!=(const BasicContainer<T>& lhs, const U& rhs) {
332  return *lhs != rhs;
333 }
334 template <typename T, typename U>
335 constexpr bool operator!=(const T& lhs, const BasicContainer<U>& rhs) {
336  return lhs != *rhs;
337 }
338 template <typename T, typename U>
339 constexpr bool operator<(const BasicContainer<T>& lhs, const U& rhs) {
340  return *lhs < rhs;
341 }
342 template <typename T, typename U>
343 constexpr bool operator<(const T& lhs, const BasicContainer<U>& rhs) {
344  return lhs < *rhs;
345 }
346 template <typename T, typename U>
347 constexpr bool operator<=(const BasicContainer<T>& lhs, const U& rhs) {
348  return *lhs <= rhs;
349 }
350 template <typename T, typename U>
351 constexpr bool operator<=(const T& lhs, const BasicContainer<U>& rhs) {
352  return lhs <= *rhs;
353 }
354 template <typename T, typename U>
355 constexpr bool operator>(const BasicContainer<T>& lhs, const U& rhs) {
356  return *lhs > rhs;
357 }
358 template <typename T, typename U>
359 constexpr bool operator>(const T& lhs, const BasicContainer<U>& rhs) {
360  return lhs > *rhs;
361 }
362 template <typename T, typename U>
363 constexpr bool operator>=(const BasicContainer<T>& lhs, const U& rhs) {
364  return *lhs >= rhs;
365 }
366 template <typename T, typename U>
367 constexpr bool operator>=(const T& lhs, const BasicContainer<U>& rhs) {
368  return lhs >= *rhs;
369 }
370 
385  private:
386  using metainformation_map_t = std::unordered_map<std::type_index, std::any>;
387  metainformation_map_t metainformations_;
388 
389  public:
393  template <typename T>
394  struct Tag {
395  public:
396  using tag_type = T;
397  };
398 
399  public:
400  MetaInformation() = default;
401  virtual ~MetaInformation() = default;
402 
403  private:
404  template <typename T>
405  constexpr void assert_static_type() {
406  // prevent usage of references
407  static_assert(std::is_reference_v<typename T::tag_type> == false,
408  "References are unsupported.");
409  }
410 
411  public:
412  template <typename T>
417  void remove() {
418  auto tindex = std::type_index(typeid(T));
419  auto iter = metainformations_.find(tindex);
420  if (iter != metainformations_.end()) {
421  metainformations_.erase(iter);
422  }
423  }
429  template <typename T>
430  void add_any(std::any metainformation_any) {
431  auto tindex = std::type_index(typeid(T));
432  auto iter = metainformations_.find(tindex);
433  if (iter != metainformations_.end()) {
434  }
435  metainformations_[tindex] = std::move(metainformation_any);
436  }
442  template <typename T>
443  const std::any* get_any() const {
444  auto tindex = std::type_index(typeid(T));
445  auto iter = metainformations_.find(tindex);
446  if (iter != metainformations_.end()) {
447  const std::any& metainformation_any = iter->second;
448  return &metainformation_any;
449  } else {
450  return nullptr;
451  }
452  }
458  template <typename T>
459  std::enable_if_t<!std::is_void_v<typename T::tag_type>, const typename T::tag_type>* get() const {
460  const std::any* metainformation_any = get_any<T>();
461  return (metainformation_any != nullptr)
462  ? std::any_cast<typename T::tag_type>(metainformation_any)
463  : nullptr;
464  }
470  template <typename T>
471  std::enable_if_t<std::is_void_v<typename T::tag_type>, bool> get() const {
472  const std::any* metainformation_any = get_any<T>();
473  return (metainformation_any != nullptr);
474  }
475 
482  template <typename T>
483  // clang-format off
484  std::enable_if_t<
485  !std::is_void_v<typename T::tag_type>
486  && !std::is_base_of_v< Tag< T >, T >
487  && std::is_move_constructible_v<typename T::tag_type>
488  >
489  // clang-format on
490  add(typename T::tag_type metainformation) {
491  assert_static_type<T>();
492 
493  std::any metainformation_any = std::move(metainformation);
494  add_any<T>(std::move(metainformation_any));
495  }
502  template <typename T>
503  // clang-format off
504  std::enable_if_t<
505  !std::is_void_v<typename T::tag_type>
506  && !std::is_base_of_v< Tag< T >, T >
507  && std::is_copy_constructible_v<typename T::tag_type>
508  && !std::is_move_constructible_v<typename T::tag_type>
509  >
510  // clang-format on
511  add(const typename T::tag_type& metainformation) {
512  assert_static_type<T>();
513 
514  std::any metainformation_any = metainformation;
515  add_any<T>(std::move(metainformation_any));
516  }
522  template <typename T>
523  // clang-format off
524  std::enable_if_t<
525  std::is_void_v<typename T::tag_type>
526  >
527  // clang-format on
528  add() {
529  std::any metainformation_any;
530  add_any<T>(std::move(metainformation_any));
531  }
550  template <typename T>
551  // clang-format off
552  std::enable_if_t<
553  std::is_base_of_v< Tag< T >, T >
554  && std::is_same_v<T, typename T::tag_type>
555  >
556  // clang-format on
557  add(T metainformation) {
558  assert_static_type<T>();
559 
560  std::any metainformation_any = std::move(metainformation);
561  add_any<T>(std::move(metainformation_any));
562  }
578  template <typename T, typename... TArgs>
579  // clang-format off
580  std::enable_if_t<
581  std::is_base_of_v< Tag< T >, T >
582  && std::is_same_v<T, typename T::tag_type>
583  >
584  // clang-format on
585  add(TArgs... args) {
586  assert_static_type<T>();
587  T metainformation(std::forward<TArgs>(args)...);
588  std::any metainformation_any = std::move(metainformation);
589  add_any<T>(std::move(metainformation_any));
590  }
591 };
592 
593 struct SignalDocumentation : MetaInformation::Tag<SignalDocumentation> {
598  std::string text;
599 
600  SignalDocumentation(std::string text_) : text{std::move(text_)} {}
601 
602  friend const std::string& to_string(const SignalDocumentation& doc) { return doc.text; }
603 };
604 
608 struct LuaAutocompletionTag : MetaInformation::Tag<LuaAutocompletionTag> {
612 #define LUADATATYPE_LIST \
613  X(Class, 0) \
614  X(Number, 1) \
615  X(String, 2)
616 
617  enum class LuaDatatype {
618 #define X(name, value) name = value,
620 #undef X
621  };
622 
623  friend std::string to_string(LuaDatatype type) {
624  switch (type) {
625 #define X(name, value) \
626  case LuaDatatype::name: \
627  return #name;
629 #undef X
630  default:
631  return {};
632  }
633  }
634 #undef LUADATATYPE_LIST
635 
639 #define PHYSICALQUANTITIES_LIST \
640  X(Dimensionless, "[]") \
641  X(Radian, "[rad]") \
642  X(Length, "[m]") \
643  X(Time, "[s]") \
644  X(Mass, "[kg]") \
645  X(Temperature, "[K]") \
646  X(ElectricCurrent, "[A]") \
647  X(Velocity, "[m/s]") \
648  X(Acceleration, "[m/s^2]") \
649  X(Jerk, "[m/s^3]") \
650  X(Jounce, "[m/s^4]") \
651  X(Crackle, "[m/s^5]")
652 
653  enum class PhysicalQuantity {
654 #define X(name, value) name,
656 #undef X
657  };
658 
659  friend std::string to_string(PhysicalQuantity type) {
660  switch (type) {
661 #define X(name, value) \
662  case PhysicalQuantity::name: \
663  return #value;
665 #undef X
666  default:
667  return {};
668  }
669  }
670 #undef PHYSICALQUANTITIES_LIST
671 
675  LuaDatatype datatype;
679  PhysicalQuantity unit;
684  std::string text;
685 
686  LuaAutocompletionTag(LuaDatatype datatype_, PhysicalQuantity unit_, std::string text_)
687  : datatype{std::move(datatype_)}, unit{std::move(unit_)}, text{std::move(text_)} {}
688 };
689 
703 class Signal {
704  private:
708  struct access_token {
709  explicit access_token(int /*unused*/){};
710  };
711 
712  public:
727  template <typename T>
728  using typed_get_value_function_t = std::function<databroker::signal_type_cref_t<T>()>;
729  using type_erased_get_value_function_t = std::any;
730 
734  template <typename T>
736  using type_erased_set_value_function_t = std::any;
740  template <typename T>
742  using type_erased_value_changed_event_t = std::any;
746  template <typename T>
748  std::function<void(databroker::signal_type_cref_t<T>)>;
749  using type_erased_on_value_change_event_function_t = std::any;
750 
751  private:
753  std::vector<std::string> names_{};
755  const std::type_info* type_{nullptr};
757  type_erased_get_value_function_t get_value_{};
759  type_erased_set_value_function_t set_value_{};
761  type_erased_value_changed_event_t value_changed_event_{};
763  type_erased_on_value_change_event_function_t on_value_changed_{};
765  std::function<std::size_t()> subscriber_count_{};
767  MetaInformation metainformations_;
768 
773  Signal() = default;
774 
775  public:
780  explicit Signal(access_token /*unused*/) : Signal() {}
781  Signal(const Signal&) = delete;
782  Signal(Signal&&) = default;
783  virtual ~Signal() = default;
784  Signal& operator=(const Signal&) = delete;
785  Signal& operator=(Signal&&) = default;
786 
790  constexpr const std::type_info* type() const { return type_; }
791 
792  private:
798  template <typename T>
799  constexpr void assert_dynamic_type() const {
800  const std::type_info* static_type = &typeid(T);
801  const std::type_info* dynamic_type = type();
802  if ((dynamic_type == nullptr) || (!(*dynamic_type == *static_type))) {
803  throw std::logic_error(
804  fmt::format("mismatch between dynamic-/actual-type and static-/requested-type; "
805  "signal type: {}, requested type: {}",
806  dynamic_type != nullptr ? dynamic_type->name() : "", static_type->name()));
807  }
808  }
809 
810  public:
824  template <typename T>
826  assert_static_type<T>();
827  assert_dynamic_type<T>();
828 
829  const typed_get_value_function_t<T>* get_value_fn =
830  std::any_cast<typed_get_value_function_t<T>>(&get_value_);
831  return get_value_fn;
832  }
833 
854  template <typename T>
856  assert_static_type<T>();
857  assert_dynamic_type<T>();
858 
859  get_value_ = std::move(get_value_fn);
860  }
861 
869  template <typename T>
871  assert_static_type<T>();
872  assert_dynamic_type<T>();
873  using compatible_type = databroker::compatible_base_t<T>;
874 
875  const typed_get_value_function_t<T>* getter_fn = getter<compatible_type>();
876  if (getter_fn && (*getter_fn)) {
877  databroker::signal_type_cref_t<T> value = getter_fn->operator()();
878  return value;
879  }
880  throw std::logic_error(
881  fmt::format("unable to get value for signal without getter-function: {}", names_.front()));
882  }
883 
890  template <typename T>
892  assert_static_type<T>();
893  assert_dynamic_type<T>();
894 
895  const typed_set_value_function_t<T>* set_value_fn =
896  std::any_cast<typed_set_value_function_t<T>>(&set_value_);
897  return set_value_fn;
898  }
899 
906  template <typename T>
908  assert_static_type<T>();
909  assert_dynamic_type<T>();
910 
911  set_value_ = std::move(set_value_fn);
912  }
913 
920  template <typename T>
922  assert_static_type<T>();
923  assert_dynamic_type<T>();
924  using compatible_type = databroker::compatible_base_t<T>;
925 
926  const typed_set_value_function_t<T>* setter_fn = setter<compatible_type>();
927  if (setter_fn && *setter_fn) {
928  setter_fn->operator()(value);
929  return;
930  }
931  throw std::logic_error(
932  fmt::format("unable to set value for signal without setter-function: {}", names_.front()));
933  }
934 
941  template <typename T>
943  assert_static_type<T>();
944  assert_dynamic_type<T>();
945 
947  std::any_cast<typed_on_value_change_event_function_t<T>>(&on_value_changed_);
948  assert(trigger_fn);
949  return *trigger_fn;
950  }
951 
959  template <typename T>
960  std::enable_if_t<!std::is_void_v<typename T::tag_type>> add(typename T::tag_type metadata) {
961  static_assert(std::is_reference_v<typename T::tag_type> == false);
962  metainformations_.add<T>(metadata);
963  }
972  template <typename T, typename... TArgs>
973  std::enable_if_t<!std::is_void_v<typename T::tag_type>> add(TArgs&&... args) {
974  static_assert(std::is_reference_v<typename T::tag_type> == false);
975  metainformations_.add<T>(std::forward<TArgs>(args)...);
976  }
977 
983  template <typename T>
984  // clang-format off
985  std::enable_if_t<
986  std::is_void_v<typename T::tag_type>
987  >
988  // clang-format on
989  add() {
990  metainformations_.add<T>();
991  }
999  template <typename T>
1000  auto metadata() -> decltype(metainformations_.get<T>()) {
1001  return metainformations_.get<T>();
1002  }
1006  const MetaInformation& metadatas() const { return metainformations_; }
1007 
1008  private:
1016  template <typename T>
1017  void subscribe_impl(
1018  const std::function<void(databroker::Event<databroker::signal_type_cref_t<T>>&)>& callback) {
1019  typed_value_changed_event_t<T>* value_changed_event =
1020  std::any_cast<typed_value_changed_event_t<T>>(&value_changed_event_);
1021  if (callback) {
1022  assert(value_changed_event);
1023  callback(*value_changed_event);
1024  }
1025  }
1026 
1027  public:
1034  template <typename T>
1036  assert_static_type<T>();
1037  assert_dynamic_type<T>();
1038 
1039  subscribe_impl<T>(
1040  [callback = std::move(callback)](typed_value_changed_event_t<T>& value_changed_event) {
1041  value_changed_event.add(std::move(callback));
1042  });
1043  }
1044 
1050  std::size_t subscriber_count() const { return subscriber_count_(); }
1051 
1057  bool has_subscriber() const { return subscriber_count() > 0; }
1058 
1064  const std::vector<std::string>& names() const { return names_; }
1065 
1071  const std::string& name() const {
1072  if (names_.empty()) {
1073  throw std::logic_error("signal does not have a name");
1074  }
1075  return names_.front();
1076  }
1077 
1083  std::string name_or(std::string def) const {
1084  if (names_.empty()) {
1085  return def;
1086  }
1087  return names_.front();
1088  }
1089 
1095  void add_name(std::string_view name) { names_.emplace_back(name); }
1096 
1097  private:
1106  template <typename T>
1107  static std::unique_ptr<Signal> make() {
1108  assert_static_type<T>();
1109  using compatible_type = databroker::compatible_base_t<T>;
1110 
1111  auto signal = std::make_unique<Signal>(access_token(0));
1112  signal->initialize<compatible_type>();
1113  return signal;
1114  }
1115 
1123  template <typename T>
1124  BasicContainer<T> create_container() {
1125  assert_static_type<T>();
1126 
1127  typed_value_changed_event_t<T>* value_changed_event =
1128  std::any_cast<typed_value_changed_event_t<T>>(&value_changed_event_);
1129  // Create container
1130  BasicContainer<T> result = BasicContainer<T>(
1131  this,
1132  [value_changed_event](databroker::signal_type_cref_t<T> value) {
1133  value_changed_event->raise(std::move(value));
1134  },
1135  typename BasicContainer<T>::access_token(0));
1136  return result;
1137  }
1138 
1139  public:
1140  private:
1141  template <typename T>
1142  void initialize() {
1143  assert_static_type<T>();
1144 
1145  type_ = &typeid(T);
1146  // Create event
1147  value_changed_event_ = typed_value_changed_event_t<T>();
1148  typed_value_changed_event_t<T>* value_changed_event =
1149  &std::any_cast<typed_value_changed_event_t<T>&>(value_changed_event_);
1150  // Create event-trigger
1151  typed_on_value_change_event_function_t<T> on_value_changed =
1152  [value_changed_event](databroker::signal_type_cref_t<T> value) {
1153  value_changed_event->raise(std::move(value));
1154  };
1155  on_value_changed_ = on_value_changed;
1156  // Create subscriber_count function
1157  subscriber_count_ = [value_changed_event]() { return value_changed_event->count(); };
1158  }
1159 
1160  template <typename T>
1161  friend class BasicContainer;
1162  friend class DataBroker;
1163 };
1164 
1165 template <typename T>
1166 void BasicContainer<T>::update_accessor_functions(BasicContainer* container) {
1167  if (signal_ != nullptr) {
1168  // Create getter-function
1169  if (container) {
1170  signal_->template set_getter<T>(
1171  [container]() -> databroker::signal_type_cref_t<T> { return container->value(); });
1172  signal_->template set_setter<T>(
1173  [container](databroker::signal_type_cref_t<T> value) { container->set_value(value); });
1174  } else {
1175  signal_->template set_getter<T>(Signal::typed_get_value_function_t<T>());
1176  signal_->template set_setter<T>(Signal::typed_set_value_function_t<T>());
1177  }
1178  }
1179 }
1180 
1181 template <typename T>
1182 bool BasicContainer<T>::has_subscriber() const {
1183  return signal_ != nullptr && signal_->has_subscriber();
1184 }
1185 
1186 template <typename T>
1187 std::size_t BasicContainer<T>::subscriber_count() const {
1188  return signal_ != nullptr ? signal_->subscriber_count() : 0;
1189 }
1190 
1194 template <typename T>
1196  private:
1197  SignalPtr signal_;
1198 
1199  public:
1200  TypedSignal(SignalPtr signal) : signal_{signal} {}
1201  ~TypedSignal() = default;
1202 
1203  operator SignalPtr&() { return signal_; }
1204  operator const SignalPtr&() const { return signal_; }
1205 
1206  const T& value() const { return signal_->template value<T>(); }
1207 
1208  template <typename TSetter>
1209  void set_setter(TSetter setter) {
1210  signal_->template set_setter<T>(std::move(setter));
1211  }
1212 };
1213 
1217 class DataBroker {
1218  public:
1219  using SignalContainer = std::map<std::string, SignalPtr, std::less<>>;
1220 
1221  private:
1222  SignalContainer signals_{};
1223  std::unordered_map<std::type_index, lua_signal_adapter_t> bindings_{};
1224  std::unordered_map<std::type_index, bool> lua_declared_types_{};
1225 
1226  public:
1227  DataBroker() = default;
1228  explicit DataBroker(const sol::state_view& lua) : lua_(lua), signals_object_(*lua_) {}
1229  DataBroker(const DataBroker&) = delete;
1230  DataBroker(DataBroker&&) = delete;
1231  ~DataBroker() = default;
1232  DataBroker& operator=(const DataBroker&) = delete;
1233  DataBroker& operator=(DataBroker&&) = delete;
1234 
1235  private:
1239  class SignalsObject {
1240  private:
1244  using lua_getter_fn = std::function<sol::object(sol::this_state&)>;
1248  using lua_setter_fn = std::function<void(sol::stack_object&)>;
1252  struct lua_accessor {
1253  lua_getter_fn getter;
1254  lua_setter_fn setter;
1255  };
1259  using accessors = std::unordered_map<std::string, lua_accessor>;
1263  accessors accessors_;
1267  sol::usertype<SignalsObject> signals_table_;
1268 
1269  public:
1270  SignalsObject(sol::state_view& lua)
1271  : accessors_()
1272  , signals_table_(lua.new_usertype<SignalsObject>(
1273  "SignalsObject", sol::meta_function::new_index, &SignalsObject::set_property_lua,
1274  sol::meta_function::index, &SignalsObject::get_property_lua)) {}
1275 
1281  sol::object get_property_lua(const char* name, sol::this_state s) {
1282  auto iter = accessors_.find(name);
1283  if (iter != accessors_.end()) {
1284  auto result = iter->second.getter(s);
1285  return result;
1286  } else {
1287  throw std::out_of_range(
1288  fmt::format("Failure to access signal '{}' from Lua since it is not bound.", name));
1289  }
1290  }
1296  void set_property_lua(const char* name, sol::stack_object object) {
1297  auto iter = accessors_.find(name);
1298  if (iter != accessors_.end()) {
1299  iter->second.setter(object);
1300  } else {
1301  throw std::out_of_range(
1302  fmt::format("Failure to access signal '{}' from Lua since it is not bound.", name));
1303  }
1304  }
1308  template <typename T>
1310  using type = T;
1311  using value_type = T;
1312  static lua_accessor make(const SignalPtr& signal) {
1313  lua_accessor result;
1314  result.getter = [signal](sol::this_state& state) -> sol::object {
1315  const value_type& value = signal->value<value_type>();
1316  return sol::make_object(state, value);
1317  };
1318  result.setter = [signal](sol::stack_object& obj) -> void {
1319  T value = obj.as<value_type>();
1320  signal->set_value<value_type>(value);
1321  };
1322  return result;
1323  }
1324  };
1329  template <typename T>
1330  struct LuaAccessorFactory<std::optional<T>> {
1331  using type = std::optional<T>;
1332  using value_type = T;
1333  static lua_accessor make(const SignalPtr& signal) {
1334  lua_accessor result;
1335  result.getter = [signal](sol::this_state& state) -> sol::object {
1336  const type& value = signal->value<type>();
1337  if (value) {
1338  return sol::make_object(state, value.value());
1339  } else {
1340  return sol::make_object(state, sol::lua_nil);
1341  }
1342  };
1343  result.setter = [signal](sol::stack_object& obj) -> void {
1344  type value;
1345  if (obj != sol::lua_nil) {
1346  value = obj.as<value_type>();
1347  }
1348  signal->set_value<type>(value);
1349  };
1350  return result;
1351  }
1352  };
1353 
1359  template <typename T>
1360  void bind(const SignalPtr& signal, std::string_view lua_name) {
1361  lua_accessor accessor = LuaAccessorFactory<T>::make(signal);
1362  auto inserted = accessors_.try_emplace(std::string(lua_name), std::move(accessor));
1363  if (!inserted.second) {
1364  throw std::out_of_range(fmt::format(
1365  "Failure adding lua-accessor for signal {}. Name already exists.", lua_name));
1366  }
1367  }
1368  };
1372  std::optional<sol::state_view> lua_{};
1376  std::optional<SignalsObject> signals_object_{};
1377 
1378  public:
1383  template <typename T>
1384  void declare_type(lua_signal_declarator_t type_declarator) {
1385  assert_static_type<T>();
1386  using compatible_type = databroker::compatible_base_t<T>;
1387 
1388  if (lua_.has_value()) {
1389  std::type_index type{typeid(compatible_type)};
1390  auto iter = lua_declared_types_.find(type);
1391  if (iter == lua_declared_types_.end()) {
1392  lua_declared_types_[type] = true;
1393  // declare type
1394  type_declarator(*lua_);
1395  }
1396  }
1397  }
1398 
1399  private:
1404  template <typename T>
1405  void declare() {
1406  assert_static_type<T>();
1407  using compatible_type = databroker::compatible_base_t<T>;
1408  if (lua_.has_value()) {
1409  // Check whether this type was already processed, if not declare it and store an adapter function in bindings_
1410  std::type_index type{typeid(compatible_type)};
1411  auto iter = bindings_.find(type);
1412  if (iter == bindings_.end()) {
1413  // Check wether this type was already declared to the Lua-VM, if not declare it
1414  auto declared_types_iter = lua_declared_types_.find(type);
1415  if (declared_types_iter == lua_declared_types_.end()) {
1416  lua_declared_types_[type] = true;
1417  ::cloe::databroker::detail::to_lua<T>(*lua_);
1418  }
1419 
1420  // Create adapter for Lua-VM
1421  lua_signal_adapter_t adapter = [this](const SignalPtr& signal, sol::state_view state,
1422  std::string_view lua_name) {
1423  //adapter_impl<T>(signal, state, lua_name);
1424  // Subscribe to the value-changed event to indicate the signal is used
1425  signal->subscribe<T>([](const T&) {});
1426  // Implement the signal as a property in Lua
1427  signals_object_->bind<T>(signal, lua_name);
1428  };
1429  // Store adapter function
1430  bindings_.emplace(type, std::move(adapter));
1431  }
1432  }
1433  }
1434 
1435  public:
1442  void bind_signal(std::string_view signal_name, std::string_view lua_name) {
1443  if (!lua_.has_value()) {
1444  throw std::logic_error(
1445  "DataBroker: Binding a signal to Lua must not happen, before binding the Lua "
1446  "context.");
1447  }
1448 
1449  SignalPtr signal = this->signal(signal_name);
1450  auto type = std::type_index(*signal->type());
1451 
1452  auto iter = bindings_.find(type);
1453  if (iter == bindings_.end()) {
1454  throw std::runtime_error(
1455  "DataBroker: <internal logic error>: Lua type binding not implemented");
1456  }
1457  const lua_signal_adapter_t& adapter = iter->second;
1458  adapter(signal, (*lua_), lua_name);
1459  }
1460 
1466  void bind_signal(std::string_view signal_name) { bind_signal(signal_name, signal_name); }
1467 
1473  void bind(std::string_view signals_name, sol::table parent) {
1474  parent[signals_name] = &(*signals_object_);
1475  }
1476 
1477  void bind(std::string_view signals_name) { (*lua_)[signals_name] = &(*signals_object_); }
1478 
1479  public:
1486  [[nodiscard]] const SignalContainer::const_iterator operator[](std::string_view name) const {
1487  SignalContainer::const_iterator iter = signals_.find(name);
1488  return iter;
1489  }
1490 
1497  [[nodiscard]] SignalContainer::iterator operator[](std::string_view name) {
1498  SignalContainer::iterator iter = signals_.find(name);
1499  return iter;
1500  }
1501 
1510  SignalPtr alias(SignalPtr signal, std::string_view new_name) {
1511  if (new_name.empty()) {
1512  throw std::invalid_argument(
1513  fmt::format("alias for signal must not be empty: {}", signal->name_or("<unnamed>")));
1514  }
1515 
1516  // Mutate signals
1517  std::pair<SignalContainer::iterator, bool> inserted =
1518  signals_.try_emplace(std::string(new_name), std::move(signal));
1519  if (!inserted.second) {
1520  throw std::out_of_range(fmt::format("cannot alias signal '{}' to '{}': name already exists",
1521  signal->name_or("<unnamed>"), new_name));
1522  }
1523  // signals mutated, there is a liability in case of exceptions
1524  try {
1525  SignalPtr result = inserted.first->second;
1526  result->add_name(new_name);
1527  return result;
1528  } catch (...) {
1529  // fullfill exception guarantee (map.erase(iter) does not throw)
1530  signals_.erase(inserted.first);
1531  throw;
1532  }
1533  }
1534 
1544  SignalPtr alias(std::string_view old_name, std::string_view new_name,
1545  std::regex::flag_type f = std::regex_constants::ECMAScript) {
1546  std::regex regex = std::regex(std::string(old_name), f);
1547  auto it1 = signals().begin();
1548  auto it2 = signals().begin();
1549  auto end = signals().end();
1550  const auto predicate = [&](const auto& item) -> bool {
1551  std::smatch match;
1552  return std::regex_match(item.first, match, regex);
1553  };
1554  it1 = (it1 != end) ? std::find_if(it1, end, predicate) : end;
1555  it2 = (it1 != end) ? std::find_if(std::next(it1), end, predicate) : end;
1556  if (it2 != end) {
1557  throw std::out_of_range(
1558  fmt::format("regex pattern matches multiple signals: '{}'; matches: '{}', '{}'", old_name,
1559  it1->first, it2->first));
1560  }
1561  if (it1 == end) {
1562  throw std::out_of_range(fmt::format("regex pattern matches zero signals: {}", old_name));
1563  return nullptr;
1564  }
1565  SignalPtr result = alias(it1->second, new_name);
1566  return result;
1567  }
1568 
1576  template <typename T>
1577  SignalPtr declare(std::string_view new_name) {
1578  assert_static_type<T>();
1579  using compatible_type = databroker::compatible_base_t<T>;
1580 
1581  declare<compatible_type>();
1582 
1583  SignalPtr signal = Signal::make<compatible_type>();
1584  alias(signal, new_name);
1585  return signal;
1586  }
1587 
1595  template <typename T>
1596  [[nodiscard]] Container<databroker::compatible_base_t<T>> implement(std::string_view new_name) {
1597  assert_static_type<T>();
1598  using compatible_type = databroker::compatible_base_t<T>;
1599 
1600  declare<compatible_type>();
1601 
1602  SignalPtr signal = declare<compatible_type>(new_name);
1603  Container<compatible_type> container = signal->create_container<compatible_type>();
1604  return container;
1605  }
1612  [[nodiscard]] SignalPtr signal(std::string_view name) const {
1613  auto iter = (*this)[name];
1614  if (iter != signals_.end()) {
1615  return iter->second;
1616  }
1617  throw std::out_of_range(fmt::format("signal not found: {}", name));
1618  }
1619 
1626  [[nodiscard]] SignalPtr signal(std::string_view name) {
1627  auto iter = (*this)[name];
1628  if (iter != signals_.end()) {
1629  return iter->second;
1630  }
1631  throw std::out_of_range(fmt::format("signal not found: {}", name));
1632  }
1633 
1637  [[nodiscard]] const SignalContainer& signals() const { return signals_; }
1638 
1642  [[nodiscard]] SignalContainer& signals() {
1643  // DRY
1644  return const_cast<SignalContainer&>(const_cast<const DataBroker*>(this)->signals());
1645  }
1646 
1654  template <typename T>
1655  void subscribe(std::string_view name, databroker::on_value_changed_callback_t<T> callback) {
1656  assert_static_type<T>();
1657  using compatible_type = databroker::compatible_base_t<T>;
1658 
1659  signal(name)->template subscribe<compatible_type>(std::move(callback));
1660  }
1661 
1669  template <typename T>
1670  void set_value(std::string_view name, databroker::signal_type_cref_t<T> value) {
1671  assert_static_type<T>();
1672  using compatible_type = databroker::compatible_base_t<T>;
1673 
1674  signal(name)->set_value<compatible_type>(value);
1675  }
1676 
1685  template <typename T>
1686  databroker::signal_type_cref_t<T> value(std::string_view name) const {
1687  assert_static_type<T>();
1688  using compatible_type = databroker::compatible_base_t<T>;
1689 
1690  return signal(name)->value<compatible_type>();
1691  }
1692 
1700  template <typename T>
1701  const Signal::typed_get_value_function_t<T>& getter(std::string_view name) const {
1702  assert_static_type<T>();
1703  using compatible_type = databroker::compatible_base_t<T>;
1704 
1705  const Signal::typed_get_value_function_t<T>* getter_fn =
1706  signal(name)->getter<compatible_type>();
1707  if (!getter_fn) {
1708  throw std::logic_error(fmt::format("getter for signal not provided: {}", name));
1709  }
1710  return *getter_fn;
1711  }
1719  template <typename T>
1720  void set_getter(std::string_view name, const Signal::typed_get_value_function_t<T>& getter_fn) {
1721  assert_static_type<T>();
1722  using compatible_type = databroker::compatible_base_t<T>;
1723 
1724  signal(name)->set_getter<compatible_type>(getter_fn);
1725  }
1726 
1734  template <typename T>
1735  const Signal::typed_set_value_function_t<T>& setter(std::string_view name) const {
1736  assert_static_type<T>();
1737  using compatible_type = databroker::compatible_base_t<T>;
1738 
1739  const Signal::typed_set_value_function_t<T>* setter_fn =
1740  signal(name)->setter<compatible_type>();
1741  if (!setter_fn) {
1742  throw std::logic_error(fmt::format("setter for signal not provided: {}", name));
1743  }
1744  return *setter_fn;
1745  }
1753  template <typename T>
1754  void set_setter(std::string_view name, const Signal::typed_set_value_function_t<T>& setter_fn) {
1755  assert_static_type<T>();
1756  using compatible_type = databroker::compatible_base_t<T>;
1757 
1758  signal(name)->set_setter<compatible_type>(setter_fn);
1759  }
1760 };
1761 
1762 namespace databroker {
1763 
1764 struct DynamicName {
1765  static constexpr bool STATIC = false;
1766 
1767  private:
1768  std::string name_;
1769 
1770  public:
1771  DynamicName(std::string name) : name_{name} {}
1772  const std::string& name() const { return name_; }
1773 };
1774 
1775 template <const char* NAME>
1776 struct StaticName {
1777  static constexpr bool STATIC = true;
1778  static constexpr const char* name() { return NAME; }
1779 };
1780 
1788 template <typename T, typename TNAME, bool = TNAME::STATIC>
1790 
1797 template <typename T, typename TNAME>
1798 struct SignalDescriptorBase<T, TNAME, true> : public TNAME {
1799  using TNAME::name;
1800  using TNAME::TNAME;
1807  static auto implement(DataBroker& db) { return db.implement<T>(name()); }
1814  static void declare(DataBroker& db) { db.declare<T>(name()); }
1821  static auto signal(const DataBroker& db) { return TypedSignal<T>(db.signal(name())); }
1828  static auto getter(const DataBroker& db) { return db.getter<T>(name()); }
1836  db.set_getter<T>(name(), std::move(get_value_fn));
1837  }
1844  static auto setter(const DataBroker& db) { return db.setter<T>(name()); }
1852  db.set_setter<T>(name(), std::move(set_value_fn));
1853  }
1854 
1861  static auto value(DataBroker& db) { return db.value<T>(name()); }
1868  static auto set_value(DataBroker& db, const T& value) { db.set_value<T>(name(), value); }
1869 };
1870 
1876 template <typename T, typename TNAME>
1877 struct SignalDescriptorBase<T, TNAME, false> : public TNAME {
1878  using TNAME::name;
1879  using TNAME::TNAME;
1886  auto implement(DataBroker& db) { return db.implement<T>(name()); }
1893  void declare(DataBroker& db) { db.declare<T>(name()); }
1900  auto signal(const DataBroker& db) const { return TypedSignal<T>(db.signal(name())); }
1907  auto getter(const DataBroker& db) const { return db.getter<T>(name()); }
1915  db.set_getter<T>(name(), std::move(get_value_fn));
1916  }
1923  auto setter(const DataBroker& db) const { return db.setter<T>(name()); }
1931  db.set_setter<T>(name(), std::move(set_value_fn));
1932  }
1933 
1940  auto value(const DataBroker& db) const { return db.value<T>(name()); }
1947  auto set_value(DataBroker& db, const T& value) { db.set_value<T>(name(), value); }
1948 };
1949 
1955 template <typename T, const char* NAME>
1956 struct SignalDescriptorImpl : public SignalDescriptorBase<T, StaticName<NAME>> {
1958 };
1964 template <typename T>
1965 struct SignalDescriptorImpl<T, nullptr> : public SignalDescriptorBase<T, DynamicName> {
1967 };
1968 
1980 template <typename T, const char* NAME = nullptr>
1981 struct SignalDescriptor : public SignalDescriptorImpl<T, NAME> {
1983 };
1984 
1985 template <typename T, const char* NAME>
1986 struct SignalTemplate : public StaticName<NAME> {
1987  private:
1988  template <template <typename> class TARGET, typename... ARGS>
1989  static auto format(ARGS&&... args) {
1990  auto name = fmt::format(StaticName<NAME>::name(), std::forward<ARGS>(args)...);
1991  return TARGET<T>(name);
1992  }
1993 
1994  public:
1995  template <typename... ARGS>
1996  static auto specialize(ARGS&&... args) {
1997  return format<SignalDescriptor>(std::forward<ARGS>(args)...);
1998  }
1999 
2000  template <typename... ARGS>
2001  static auto partial(ARGS&&... args) {
2002  return format<SignalTemplate>(std::forward<ARGS>(args)...);
2003  }
2004 };
2005 
2006 // template <typename T, const char* NAME>
2007 // struct SignalDescriptor : public SignalDescriptor<T, StaticName<NAME>> {
2008 //using type = typename SignalDescriptorImpl<T, NAME>::type;
2009 // };
2010 
2011 // template <typename T>
2012 // struct IsSignalDescriptor : std::false_type {};
2013 // template <typename T, const char* NAME>
2014 // struct IsSignalDescriptor<SignalDescriptor<T, NAME>> : std::true_type {};
2015 // template <typename T>
2016 // constexpr bool is_signal_descriptor_v() {
2017 // return IsSignalDescriptor<T>::value;
2018 // }
2019 
2020 } // namespace databroker
2021 
2022 // Design-Goals:
2023 // -g1: Prepare for mass usage of Signals, Containers & Databroker
2024 // ==> Allow instantiation of all templates for relevant datatypes
2025 // -g2: Pre-Instantiate these templates for datatypes which are already known to be relevant
2026 
2027 #define CLOE_DATABROKER_TEMPLATE_INSTANTIATION(elem) \
2028  extern template class BasicContainer<elem>; \
2029  extern template const Signal::typed_get_value_function_t<elem>* Signal::getter<elem>() const; \
2030  extern template void Signal::set_getter<elem>(Signal::typed_get_value_function_t<elem>); \
2031  extern template databroker::signal_type_cref_t<elem> Signal::value<elem>() const; \
2032  extern template const Signal::typed_set_value_function_t<elem>* Signal::setter<elem>() const; \
2033  extern template void Signal::set_setter<elem>(Signal::typed_set_value_function_t<elem>); \
2034  extern template void Signal::set_value<elem>(databroker::signal_type_cref_t<elem> value) const; \
2035  extern template const Signal::typed_on_value_change_event_function_t<elem>& \
2036  Signal::trigger<elem>() const; \
2037  extern template void Signal::subscribe_impl<elem>( \
2038  const std::function<void(databroker::Event<databroker::signal_type_cref_t<elem>>&)>&); \
2039  extern template void Signal::subscribe<elem>(databroker::on_value_changed_callback_t<elem>); \
2040  extern template std::unique_ptr<Signal> Signal::make<elem>(); \
2041  extern template BasicContainer<elem> Signal::create_container<elem>(); \
2042  extern template void Signal::initialize<elem>(); \
2043  extern template SignalPtr DataBroker::declare<elem>(std::string_view); \
2044  extern template BasicContainer<elem> DataBroker::implement<elem>(std::string_view); \
2045  extern template void DataBroker::subscribe<elem>(std::string_view, \
2046  databroker::on_value_changed_callback_t<elem>); \
2047  extern template databroker::signal_type_cref_t<elem> DataBroker::value<elem>(std::string_view); \
2048  extern template const Signal::typed_get_value_function_t<elem>& DataBroker::getter<elem>( \
2049  std::string_view name); \
2050  extern template void DataBroker::set_value<elem>(std::string_view, \
2051  databroker::signal_type_cref_t<elem>); \
2052  extern template const Signal::typed_set_value_function_t<elem>& DataBroker::setter<elem>( \
2053  std::string_view name);
2054 
2055 #define CLOE_DATABROKER_TEMPLATE_INSTANTATION_TYPES()
2056 
2057 CLOE_DATABROKER_TEMPLATE_INSTANTATION_TYPES()
2058 
2059 // Goal g1 implies that the preprocessor macros are not undefined.
2060 
2061 } // namespace cloe
2062 
2063 #endif // CLOE_DATA_BROKER_HPP_
Definition: data_broker.hpp:226
Definition: data_broker.hpp:1217
void set_value(std::string_view name, databroker::signal_type_cref_t< T > value)
Definition: data_broker.hpp:1670
const Signal::typed_set_value_function_t< T > & setter(std::string_view name) const
Definition: data_broker.hpp:1735
SignalPtr alias(SignalPtr signal, std::string_view new_name)
Definition: data_broker.hpp:1510
SignalContainer & signals()
Definition: data_broker.hpp:1642
void bind(std::string_view signals_name, sol::table parent)
Binds the signals-object to Lua.
Definition: data_broker.hpp:1473
const SignalContainer & signals() const
Definition: data_broker.hpp:1637
const Signal::typed_get_value_function_t< T > & getter(std::string_view name) const
Definition: data_broker.hpp:1701
void bind_signal(std::string_view signal_name, std::string_view lua_name)
Binds a signal to the Lua-VM.
Definition: data_broker.hpp:1442
SignalPtr signal(std::string_view name)
Definition: data_broker.hpp:1626
void set_getter(std::string_view name, const Signal::typed_get_value_function_t< T > &getter_fn)
Definition: data_broker.hpp:1720
SignalPtr declare(std::string_view new_name)
Definition: data_broker.hpp:1577
SignalPtr alias(std::string_view old_name, std::string_view new_name, std::regex::flag_type f=std::regex_constants::ECMAScript)
Definition: data_broker.hpp:1544
void declare_type(lua_signal_declarator_t type_declarator)
Declares a DataType to Lua (if not yet done)
Definition: data_broker.hpp:1384
SignalContainer::iterator operator[](std::string_view name)
Definition: data_broker.hpp:1497
void set_setter(std::string_view name, const Signal::typed_set_value_function_t< T > &setter_fn)
Definition: data_broker.hpp:1754
void bind_signal(std::string_view signal_name)
Binds a signal to the Lua-VM.
Definition: data_broker.hpp:1466
databroker::signal_type_cref_t< T > value(std::string_view name) const
Definition: data_broker.hpp:1686
const SignalContainer::const_iterator operator[](std::string_view name) const
Definition: data_broker.hpp:1486
Container< databroker::compatible_base_t< T > > implement(std::string_view new_name)
Definition: data_broker.hpp:1596
SignalPtr signal(std::string_view name) const
Definition: data_broker.hpp:1612
void subscribe(std::string_view name, databroker::on_value_changed_callback_t< T > callback)
Definition: data_broker.hpp:1655
Definition: data_broker.hpp:384
std::enable_if_t< std::is_base_of_v< Tag< T >, T > &&std::is_same_v< T, typename T::tag_type > > add(TArgs... args)
Definition: data_broker.hpp:585
void remove()
Definition: data_broker.hpp:417
std::enable_if_t< std::is_void_v< typename T::tag_type > > add()
Definition: data_broker.hpp:528
std::enable_if_t< std::is_base_of_v< Tag< T >, T > &&std::is_same_v< T, typename T::tag_type > > add(T metainformation)
Definition: data_broker.hpp:557
void add_any(std::any metainformation_any)
Definition: data_broker.hpp:430
const std::any * get_any() const
Definition: data_broker.hpp:443
std::enable_if_t< !std::is_void_v< typename T::tag_type > &&!std::is_base_of_v< Tag< T >, T > &&std::is_move_constructible_v< typename T::tag_type > > add(typename T::tag_type metainformation)
Definition: data_broker.hpp:490
std::enable_if_t< std::is_void_v< typename T::tag_type >, bool > get() const
Definition: data_broker.hpp:471
std::enable_if_t<!std::is_void_v< typename T::tag_type >, const typename T::tag_type > * get() const
Definition: data_broker.hpp:459
std::enable_if_t< !std::is_void_v< typename T::tag_type > &&!std::is_base_of_v< Tag< T >, T > &&std::is_copy_constructible_v< typename T::tag_type > &&!std::is_move_constructible_v< typename T::tag_type > > add(const typename T::tag_type &metainformation)
Definition: data_broker.hpp:511
Definition: data_broker.hpp:703
std::enable_if_t<!std::is_void_v< typename T::tag_type > > add(TArgs &&... args)
Definition: data_broker.hpp:973
bool has_subscriber() const
Definition: data_broker.hpp:1057
const MetaInformation & metadatas() const
Definition: data_broker.hpp:1006
const typed_on_value_change_event_function_t< T > & trigger() const
Definition: data_broker.hpp:942
std::function< void(databroker::signal_type_cref_t< T >)> typed_on_value_change_event_function_t
Definition: data_broker.hpp:748
void set_getter(typed_get_value_function_t< T > get_value_fn)
Definition: data_broker.hpp:855
const typed_set_value_function_t< T > * setter() const
Definition: data_broker.hpp:891
const typed_get_value_function_t< T > * getter() const
Definition: data_broker.hpp:825
void set_setter(typed_set_value_function_t< T > set_value_fn)
Definition: data_broker.hpp:907
void add_name(std::string_view name)
Definition: data_broker.hpp:1095
std::function< void(databroker::signal_type_cref_t< T >)> typed_set_value_function_t
Definition: data_broker.hpp:735
std::function< databroker::signal_type_cref_t< T >()> typed_get_value_function_t
Definition: data_broker.hpp:728
const std::vector< std::string > & names() const
Definition: data_broker.hpp:1064
std::enable_if_t< std::is_void_v< typename T::tag_type > > add()
Definition: data_broker.hpp:989
std::size_t subscriber_count() const
Definition: data_broker.hpp:1050
const std::string & name() const
Definition: data_broker.hpp:1071
void set_value(databroker::signal_type_cref_t< T > value) const
Definition: data_broker.hpp:921
auto metadata() -> decltype(metainformations_.get< T >())
Definition: data_broker.hpp:1000
Signal(access_token)
Definition: data_broker.hpp:780
constexpr const std::type_info * type() const
Definition: data_broker.hpp:790
std::enable_if_t<!std::is_void_v< typename T::tag_type > > add(typename T::tag_type metadata)
Definition: data_broker.hpp:960
databroker::signal_type_cref_t< T > value() const
Definition: data_broker.hpp:870
void subscribe(databroker::on_value_changed_callback_t< T > callback)
Definition: data_broker.hpp:1035
std::string name_or(std::string def) const
Definition: data_broker.hpp:1083
Definition: data_broker.hpp:1195
Definition: data_broker.hpp:154
std::size_t count() const
Definition: data_broker.hpp:170
void add(EventHandler handler)
Definition: data_broker.hpp:165
constexpr bool is_incompatible_type_v
Definition: data_broker.hpp:120
std::function< void(const SignalPtr &, sol::state_view, std::string_view)> lua_signal_adapter_t
Definition: data_broker.hpp:215
#define PHYSICALQUANTITIES_LIST
Definition: data_broker.hpp:639
void to_lua(sol::state_view lua)
Definition: data_broker.hpp:90
constexpr void assert_static_type()
Definition: data_broker.hpp:199
#define LUADATATYPE_LIST
Definition: data_broker.hpp:612
typename type_t_or_int_if< T, !is_incompatible_type_v< T > >::type compatible_base_t
Definition: data_broker.hpp:132
std::function< void(signal_type_cref_t< T >)> on_value_changed_callback_t
Definition: data_broker.hpp:144
std::function< void(sol::state_view)> lua_signal_declarator_t
Definition: data_broker.hpp:220
constexpr bool has_to_lua_v
Definition: data_broker.hpp:84
databroker::compatible_base_t< T > const & signal_type_cref_t
Definition: data_broker.hpp:138
Definition: data_broker.hpp:608
LuaDatatype datatype
Definition: data_broker.hpp:675
PhysicalQuantity unit
Definition: data_broker.hpp:679
std::string text
Definition: data_broker.hpp:684
Definition: data_broker.hpp:394
Definition: data_broker.hpp:593
std::string text
Definition: data_broker.hpp:598
Definition: data_broker.hpp:1764
void set_setter(DataBroker &db, Signal::typed_set_value_function_t< T > set_value_fn)
Definition: data_broker.hpp:1930
auto set_value(DataBroker &db, const T &value)
Definition: data_broker.hpp:1947
auto value(const DataBroker &db) const
Definition: data_broker.hpp:1940
auto setter(const DataBroker &db) const
Definition: data_broker.hpp:1923
void declare(DataBroker &db)
Definition: data_broker.hpp:1893
auto getter(const DataBroker &db) const
Definition: data_broker.hpp:1907
auto signal(const DataBroker &db) const
Definition: data_broker.hpp:1900
auto implement(DataBroker &db)
Definition: data_broker.hpp:1886
void set_getter(DataBroker &db, Signal::typed_get_value_function_t< T > get_value_fn)
Definition: data_broker.hpp:1914
static auto value(DataBroker &db)
Definition: data_broker.hpp:1861
static auto setter(const DataBroker &db)
Definition: data_broker.hpp:1844
static void set_setter(DataBroker &db, Signal::typed_set_value_function_t< T > set_value_fn)
Definition: data_broker.hpp:1851
static auto set_value(DataBroker &db, const T &value)
Definition: data_broker.hpp:1868
static auto implement(DataBroker &db)
Definition: data_broker.hpp:1807
static void set_getter(DataBroker &db, Signal::typed_get_value_function_t< T > get_value_fn)
Definition: data_broker.hpp:1835
static auto getter(const DataBroker &db)
Definition: data_broker.hpp:1828
static auto signal(const DataBroker &db)
Definition: data_broker.hpp:1821
static void declare(DataBroker &db)
Definition: data_broker.hpp:1814
Definition: data_broker.hpp:1789
Definition: data_broker.hpp:1956
Definition: data_broker.hpp:1981
Definition: data_broker.hpp:1986
Definition: data_broker.hpp:1776
Definition: data_broker.hpp:72
Definition: data_broker.hpp:106