| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- #ifndef DEPTHGUIDE_OBJECT_MANAGER_H
- #define DEPTHGUIDE_OBJECT_MANAGER_H
- #include "core/utility.hpp"
- #include <boost/asio/post.hpp>
- #include <boost/asio/io_context.hpp>
- #include <boost/signals2.hpp>
- #include <cassert>
- #include <cstdint>
- #include <functional>
- #include <memory>
- #include <optional>
- #include <typeindex>
- #include <typeinfo>
- class object_manager {
- public:
- using name_type = uint16_t;
- using io_context = boost::asio::io_context;
- struct create_config {
- io_context *ctx = nullptr;
- };
- explicit object_manager(create_config conf);
- ~object_manager();
- // thread-safe
- template<typename T>
- void save(name_type obj_name, T &&val) {
- using RT = std::remove_cvref_t<T>;
- if (auto ctx = switch_ctx(); ctx != nullptr) [[unlikely]] {
- using boost::asio::post;
- static_assert(std::is_copy_constructible_v<RT>);
- post(*ctx, [=, rt_val = RT(val), this] { save(obj_name, rt_val); });
- return;
- }
- auto pl_ptr = query_placeholder(obj_name, typeid(RT));
- if (pl_ptr == nullptr) [[unlikely]] {
- static_assert(std::is_default_constructible_v<RT>);
- create_placeholder(obj_name, typeid(RT),
- new RT{}, [](void *ptr) { delete (RT *) ptr; });
- pl_ptr = query_placeholder(obj_name, typeid(RT));
- }
- assert(pl_ptr != nullptr);
- static_assert(std::is_copy_assignable_v<RT>);
- *(RT *) pl_ptr = val;
- notify_signal(obj_name);
- }
- template<typename T>
- T query(name_type obj_name) {
- auto pl_ptr = query_placeholder(obj_name, typeid(T));
- assert(pl_ptr != nullptr);
- static_assert(std::is_copy_constructible_v<T>);
- return *(T *) pl_ptr;
- }
- std::type_index query_type(name_type obj_name) {
- auto info_o = query_info(obj_name);
- assert(info_o.has_value());
- return info_o->type;
- }
- timestamp_type query_save_ts(name_type obj_name) {
- auto info_o = query_info(obj_name);
- assert(info_o.has_value());
- return info_o->last_save_ts;
- }
- using obj_sig_type = boost::signals2::signal<void(name_type)>;
- obj_sig_type *query_signal(name_type obj_name) {
- auto info_o = query_info(obj_name);
- assert(info_o.has_value());
- return info_o->sig;
- }
- struct obj_stats {
- float save_interval = 0.0f; // in ms
- float save_frequency = 0.0f; // in Hz
- };
- obj_stats query_obj_stats(name_type obj_name);
- private:
- using del_func_type = void (*)(void *);
- struct obj_info {
- std::type_index type = typeid(void);
- void *pl_ptr = nullptr;
- obj_sig_type *sig = nullptr;
- timestamp_type last_save_ts = 0;
- };
- std::optional<obj_info> query_info(name_type obj_name);
- void *query_placeholder(name_type obj_name, std::type_index obj_type) {
- auto info_o = query_info(obj_name);
- if (!info_o.has_value()) [[unlikely]] return nullptr;
- if (info_o->type != obj_type) return nullptr;
- return info_o->pl_ptr;
- }
- void create_placeholder(name_type obj_name, std::type_index obj_type,
- void *ptr, del_func_type del_func);
- void notify_signal(name_type obj_name);
- // return target context or nullptr
- io_context *switch_ctx();
- struct impl;
- std::unique_ptr<impl> pimpl;
- };
- using obj_name_type = object_manager::name_type;
- static constexpr obj_name_type invalid_obj_name = -1;
- extern object_manager *main_ob;
- #define OBJ_QUERY(type, name) \
- main_ob->query<type>(name)
- #define OBJ_TYPE(name) \
- main_ob->query_type(name)
- #define OBJ_SAVE_TS(name) \
- main_ob->query_save_ts(name)
- #define OBJ_STATS(name) \
- main_ob->query_obj_stats(name)
- #define OBJ_SAVE(name, val) \
- main_ob->save(name, val)
- #define OBJ_SIG(name) \
- main_ob->query_signal(name)
- #endif //DEPTHGUIDE_OBJECT_MANAGER_H
|