#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 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 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 variable_delegate &operator=(T &&val) { set_value(std::forward(val)); return *this; } const SmallObjType &operator*() { assert(!empty()); return *get_value(); } const SmallObjType *operator->() { assert(!empty()); return get_value().get(); } boost::asio::awaitable 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 using variable_auto_sync_delegate = variable_delegate; template using variable_manual_sync_delegate = variable_delegate; #define VARIABLE_AUTO_DELEGATE(var_type, var_index) \ variable_auto_sync_delegate(var_index) #define VARIABLE_MANUAL_DELEGATE(var_type, var_index) \ variable_manual_sync_delegate(var_index) template 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 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 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 std::enable_if_t()( std::declval())), bool>, boost::asio::awaitable> 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 boost::asio::awaitable 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 boost::asio::awaitable 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