variable_helper.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. void manual_sync() {
  32. if (watcher.try_wait()) { // new value available
  33. val_ptr = QUERY_VARIABLE(SmallObjType, var_index);
  34. }
  35. }
  36. pointer_type get_value() {
  37. if constexpr (AutoSync) {
  38. manual_sync();
  39. }
  40. return val_ptr;
  41. }
  42. timestamp_type get_last_update_ts() const {
  43. return watcher.get_last_update_ts();
  44. }
  45. bool empty() {
  46. return get_value() == nullptr;
  47. }
  48. template<typename T>
  49. variable_delegate &operator=(T &&val) {
  50. set_value(std::forward<T>(val));
  51. return *this;
  52. }
  53. const SmallObjType &operator*() {
  54. assert(!empty());
  55. return *get_value();
  56. }
  57. const SmallObjType *operator->() {
  58. assert(!empty());
  59. return get_value().get();
  60. }
  61. boost::asio::awaitable<void> coro_wait_update(bool auto_sync = AutoSync) {
  62. co_await watcher.coro_wait(auto_sync);
  63. val_ptr = QUERY_VARIABLE(SmallObjType, var_index);
  64. co_return;
  65. }
  66. private:
  67. variable_index_type var_index;
  68. pointer_type val_ptr;
  69. signal_watcher watcher;
  70. };
  71. template<typename SmallObjType>
  72. using variable_auto_sync_delegate = variable_delegate<SmallObjType, true>;
  73. template<typename SmallObjType>
  74. using variable_manual_sync_delegate = variable_delegate<SmallObjType, false>;
  75. #define VARIABLE_AUTO_DELEGATE(var_type, var_index) \
  76. variable_auto_sync_delegate<var_type>(var_index)
  77. #define VARIABLE_MANUAL_DELEGATE(var_type, var_index) \
  78. variable_manual_sync_delegate<var_type>(var_index)
  79. template<typename SmallObjType>
  80. auto try_query_variable_value(variable_index_type var_index,
  81. const typename SmallObjType::value_type &default_value) {
  82. if (!is_valid_id(var_index)) return default_value;
  83. auto var_ptr = QUERY_VARIABLE(SmallObjType, var_index);
  84. if (var_ptr == nullptr) return default_value;
  85. return var_ptr->value;
  86. }
  87. template<typename SmallObjType>
  88. auto try_update_variable(variable_index_type var_index,
  89. typename SmallObjType::pointer &&ptr,
  90. timestamp_type ts = current_timestamp()) {
  91. if (!is_valid_id(var_index)) return;
  92. UPDATE_VARIABLE_WITH_TS(SmallObjType, var_index, ptr, ts);
  93. }
  94. template<typename SmallObjType>
  95. auto try_update_variable_value(variable_index_type var_index,
  96. const typename SmallObjType::value_type &value,
  97. timestamp_type ts = current_timestamp()) {
  98. if (!is_valid_id(var_index)) return;
  99. UPDATE_VARIABLE_VAL_WITH_TS(SmallObjType, var_index, value, ts);
  100. }
  101. template<typename SmallObjType, typename CondFuncType>
  102. std::enable_if_t<std::is_convertible_v<
  103. decltype(std::declval<CondFuncType>()(
  104. std::declval<typename SmallObjType::value_type>())),
  105. bool>, boost::asio::awaitable<void>>
  106. coro_wait_for_variable_value(variable_index_type var_index,
  107. CondFuncType &&cond_func) {
  108. auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
  109. var_helper.manual_sync();
  110. for (;;) {
  111. if (!var_helper.empty() &&
  112. cond_func(var_helper->value)) {
  113. break;
  114. }
  115. co_await var_helper.coro_wait_update();
  116. }
  117. co_return;
  118. }
  119. template<typename SmallObjType,
  120. typename ValueType = typename SmallObjType::value_type>
  121. boost::asio::awaitable<void> coro_wait_for_variable_value(variable_index_type var_index,
  122. const ValueType &val_tar) {
  123. auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
  124. var_helper.manual_sync();
  125. for (;;) {
  126. if (!var_helper.empty() &&
  127. var_helper->value == val_tar) {
  128. break;
  129. }
  130. co_await var_helper.coro_wait_update();
  131. }
  132. co_return;
  133. }
  134. }
  135. #endif //SOPHIAR2_VARIABLE_HELPER_HPP