variable_helper.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #ifndef SOPHIAR2_VARIABLE_HELPER_HPP
  2. #define SOPHIAR2_VARIABLE_HELPER_HPP
  3. #include "core/global_defs.h"
  4. #include "core/small_obj.hpp"
  5. #include "core/sophiar_pool.h"
  6. #include "utility/coro_signal2.hpp"
  7. namespace sophiar {
  8. template<typename SmallObjType, bool AutoSync = true>
  9. class variable_delegate {
  10. public:
  11. using pointer_type = typename SmallObjType::pointer;
  12. explicit variable_delegate(variable_index_type _var_index)
  13. : watcher(REQUIRE_VARIABLE_WATCHER(_var_index)),
  14. var_index(_var_index) {}
  15. explicit variable_delegate(std::string_view obj_name)
  16. : variable_delegate(REQUIRE_VARIABLE(SmallObjType, obj_name)) {}
  17. variable_delegate(variable_delegate &&other) noexcept = default;
  18. signal_watcher new_watcher() const {
  19. return REQUIRE_VARIABLE_WATCHER(var_index);
  20. }
  21. void set_value(const pointer_type &ptr,
  22. timestamp_type ts = current_timestamp()) {
  23. UPDATE_VARIABLE_WITH_TS(SmallObjType, var_index, ptr, ts);
  24. }
  25. template<typename OtherSmallObjType = SmallObjType,
  26. typename ValueType = OtherSmallObjType::value_type>
  27. void set_value(const ValueType &val,
  28. timestamp_type ts = current_timestamp()) {
  29. UPDATE_VARIABLE_VAL_WITH_TS(SmallObjType, var_index, val, ts);
  30. }
  31. // return true if received new value
  32. bool manual_sync() {
  33. if (watcher.try_wait()) { // new value available
  34. val_ptr = QUERY_VARIABLE(SmallObjType, var_index);
  35. return true;
  36. }
  37. return false;
  38. }
  39. pointer_type get_value() {
  40. if constexpr (AutoSync) {
  41. manual_sync();
  42. }
  43. return val_ptr;
  44. }
  45. timestamp_type get_last_update_ts() const {
  46. return watcher.get_last_update_ts();
  47. }
  48. bool empty() {
  49. return get_value() == nullptr;
  50. }
  51. template<typename T>
  52. variable_delegate &operator=(T &&val) {
  53. set_value(std::forward<T>(val));
  54. return *this;
  55. }
  56. const SmallObjType &operator*() {
  57. assert(!empty());
  58. return *get_value();
  59. }
  60. const SmallObjType *operator->() {
  61. assert(!empty());
  62. return get_value().get();
  63. }
  64. boost::asio::awaitable<void> coro_wait_update(bool auto_sync = AutoSync) {
  65. co_await watcher.coro_wait(auto_sync);
  66. val_ptr = QUERY_VARIABLE(SmallObjType, var_index);
  67. co_return;
  68. }
  69. private:
  70. variable_index_type var_index;
  71. pointer_type val_ptr;
  72. signal_watcher watcher;
  73. };
  74. template<typename SmallObjType>
  75. using variable_auto_sync_delegate = variable_delegate<SmallObjType, true>;
  76. template<typename SmallObjType>
  77. using variable_manual_sync_delegate = variable_delegate<SmallObjType, false>;
  78. #define VARIABLE_AUTO_DELEGATE(var_type, var_index) \
  79. variable_auto_sync_delegate<var_type>(var_index)
  80. #define VARIABLE_MANUAL_DELEGATE(var_type, var_index) \
  81. variable_manual_sync_delegate<var_type>(var_index)
  82. template<typename SmallObjType>
  83. auto try_query_variable_value(variable_index_type var_index,
  84. const typename SmallObjType::value_type &default_value) {
  85. if (!is_valid_id(var_index)) return default_value;
  86. auto var_ptr = QUERY_VARIABLE(SmallObjType, var_index);
  87. if (var_ptr == nullptr) return default_value;
  88. return var_ptr->value;
  89. }
  90. template<typename SmallObjType>
  91. auto try_update_variable(variable_index_type var_index,
  92. typename SmallObjType::pointer &&ptr,
  93. timestamp_type ts = current_timestamp()) {
  94. if (!is_valid_id(var_index)) return;
  95. UPDATE_VARIABLE_WITH_TS(SmallObjType, var_index, ptr, ts);
  96. }
  97. template<typename SmallObjType>
  98. auto try_update_variable_value(variable_index_type var_index,
  99. const typename SmallObjType::value_type &value,
  100. timestamp_type ts = current_timestamp()) {
  101. if (!is_valid_id(var_index)) return;
  102. UPDATE_VARIABLE_VAL_WITH_TS(SmallObjType, var_index, value, ts);
  103. }
  104. template<typename SmallObjType, typename CondFuncType>
  105. std::enable_if_t<std::is_convertible_v<
  106. decltype(std::declval<CondFuncType>()(
  107. std::declval<typename SmallObjType::value_type>())),
  108. bool>, boost::asio::awaitable<void>>
  109. coro_wait_for_variable_value(variable_index_type var_index,
  110. CondFuncType &&cond_func) {
  111. auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
  112. var_helper.manual_sync();
  113. for (;;) {
  114. if (!var_helper.empty() &&
  115. cond_func(var_helper->value)) {
  116. break;
  117. }
  118. co_await var_helper.coro_wait_update();
  119. }
  120. co_return;
  121. }
  122. template<typename SmallObjType,
  123. typename ValueType = typename SmallObjType::value_type>
  124. boost::asio::awaitable<void> coro_wait_for_variable_value(variable_index_type var_index,
  125. const ValueType &val_tar) {
  126. auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
  127. var_helper.manual_sync();
  128. for (;;) {
  129. if (!var_helper.empty() &&
  130. var_helper->value == val_tar) {
  131. break;
  132. }
  133. co_await var_helper.coro_wait_update();
  134. }
  135. co_return;
  136. }
  137. template<typename SmallObjType>
  138. boost::asio::awaitable<void> coro_wait_for_not_empty(variable_index_type var_index) {
  139. auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
  140. var_helper.manual_sync();
  141. for (;;) {
  142. if (!var_helper.empty()) {
  143. break;
  144. }
  145. co_await var_helper.coro_wait_update();
  146. }
  147. co_return;
  148. }
  149. }
  150. #endif //SOPHIAR2_VARIABLE_HELPER_HPP