| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- #ifndef SOPHIAR2_VARIABLE_HELPER_HPP
- #define SOPHIAR2_VARIABLE_HELPER_HPP
- #include "core/global_defs.h"
- #include "core/small_obj.hpp"
- #include "core/sophiar_pool.h"
- #include "utility/coro_signal2.hpp"
- namespace sophiar {
- template<typename SmallObjType, bool AutoSync = true>
- class variable_delegate {
- public:
- using pointer_type = typename SmallObjType::pointer;
- explicit variable_delegate(variable_index_type _var_index)
- : watcher(REQUIRE_VARIABLE_WATCHER(_var_index)),
- var_index(_var_index) {}
- explicit variable_delegate(std::string_view obj_name)
- : variable_delegate(REQUIRE_VARIABLE(SmallObjType, obj_name)) {}
- variable_delegate(variable_delegate &&other) noexcept = default;
- signal_watcher new_watcher() const {
- return REQUIRE_VARIABLE_WATCHER(var_index);
- }
- void set_value(const pointer_type &ptr,
- timestamp_type ts = current_timestamp()) {
- UPDATE_VARIABLE_WITH_TS(SmallObjType, var_index, ptr, ts);
- }
- template<typename OtherSmallObjType = SmallObjType,
- typename ValueType = OtherSmallObjType::value_type>
- void set_value(const ValueType &val,
- timestamp_type ts = current_timestamp()) {
- UPDATE_VARIABLE_VAL_WITH_TS(SmallObjType, var_index, val, ts);
- }
- // return true if received new value
- bool manual_sync() {
- if (watcher.try_wait()) { // new value available
- val_ptr = QUERY_VARIABLE(SmallObjType, var_index);
- return true;
- }
- return false;
- }
- pointer_type get_value() {
- if constexpr (AutoSync) {
- manual_sync();
- }
- return val_ptr;
- }
- timestamp_type get_last_update_ts() const {
- return watcher.get_last_update_ts();
- }
- bool empty() {
- return get_value() == nullptr;
- }
- template<typename T>
- variable_delegate &operator=(T &&val) {
- set_value(std::forward<T>(val));
- return *this;
- }
- const SmallObjType &operator*() {
- assert(!empty());
- return *get_value();
- }
- const SmallObjType *operator->() {
- assert(!empty());
- return get_value().get();
- }
- boost::asio::awaitable<void> coro_wait_update(bool auto_sync = AutoSync) {
- co_await watcher.coro_wait(auto_sync);
- val_ptr = QUERY_VARIABLE(SmallObjType, var_index);
- co_return;
- }
- private:
- variable_index_type var_index;
- pointer_type val_ptr;
- signal_watcher watcher;
- };
- template<typename SmallObjType>
- using variable_auto_sync_delegate = variable_delegate<SmallObjType, true>;
- template<typename SmallObjType>
- using variable_manual_sync_delegate = variable_delegate<SmallObjType, false>;
- #define VARIABLE_AUTO_DELEGATE(var_type, var_index) \
- variable_auto_sync_delegate<var_type>(var_index)
- #define VARIABLE_MANUAL_DELEGATE(var_type, var_index) \
- variable_manual_sync_delegate<var_type>(var_index)
- template<typename SmallObjType>
- auto try_query_variable_value(variable_index_type var_index,
- const typename SmallObjType::value_type &default_value) {
- if (!is_valid_id(var_index)) return default_value;
- auto var_ptr = QUERY_VARIABLE(SmallObjType, var_index);
- if (var_ptr == nullptr) return default_value;
- return var_ptr->value;
- }
- template<typename SmallObjType>
- auto try_update_variable(variable_index_type var_index,
- typename SmallObjType::pointer &&ptr,
- timestamp_type ts = current_timestamp()) {
- if (!is_valid_id(var_index)) return;
- UPDATE_VARIABLE_WITH_TS(SmallObjType, var_index, ptr, ts);
- }
- template<typename SmallObjType>
- auto try_update_variable_value(variable_index_type var_index,
- const typename SmallObjType::value_type &value,
- timestamp_type ts = current_timestamp()) {
- if (!is_valid_id(var_index)) return;
- UPDATE_VARIABLE_VAL_WITH_TS(SmallObjType, var_index, value, ts);
- }
- template<typename SmallObjType, typename CondFuncType>
- std::enable_if_t<std::is_convertible_v<
- decltype(std::declval<CondFuncType>()(
- std::declval<typename SmallObjType::value_type>())),
- bool>, boost::asio::awaitable<void>>
- coro_wait_for_variable_value(variable_index_type var_index,
- CondFuncType &&cond_func) {
- auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
- var_helper.manual_sync();
- for (;;) {
- if (!var_helper.empty() &&
- cond_func(var_helper->value)) {
- break;
- }
- co_await var_helper.coro_wait_update();
- }
- co_return;
- }
- template<typename SmallObjType,
- typename ValueType = typename SmallObjType::value_type>
- boost::asio::awaitable<void> coro_wait_for_variable_value(variable_index_type var_index,
- const ValueType &val_tar) {
- auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
- var_helper.manual_sync();
- for (;;) {
- if (!var_helper.empty() &&
- var_helper->value == val_tar) {
- break;
- }
- co_await var_helper.coro_wait_update();
- }
- co_return;
- }
- template<typename SmallObjType>
- boost::asio::awaitable<void> coro_wait_for_not_empty(variable_index_type var_index) {
- auto var_helper = VARIABLE_MANUAL_DELEGATE(SmallObjType, var_index);
- var_helper.manual_sync();
- for (;;) {
- if (!var_helper.empty()) {
- break;
- }
- co_await var_helper.coro_wait_update();
- }
- co_return;
- }
- }
- #endif //SOPHIAR2_VARIABLE_HELPER_HPP
|