#ifndef META_HELPER_H #define META_HELPER_H #include #include #include #include struct meta_base_v2 { // using key_type = std::size_t; using key_type = std::string; using value_type = boost::any; using meta_map_type = std::unordered_map; meta_map_type meta; std::shared_mutex mu; void insert(auto &&key, const value_type &value) { using Key = decltype(key); auto lock = std::unique_lock(mu); if constexpr (std::is_convertible_v) { const auto key_hash = (key_type) key; meta[key_hash] = value; } else { // const auto key_hash = std::hash()(key); const auto key_hash = std::to_string(key); meta[key_hash] = value; } } void merge(meta_base_v2 &o) { if (this == &o) return; //@formatter:off auto read_lock = std::shared_lock(o.mu, std::defer_lock); auto write_lock = std::unique_lock(mu, std::defer_lock); assert(&o.mu != &mu); if (&o.mu < &mu) { read_lock.lock(); write_lock.lock(); } else { write_lock.lock(); read_lock.lock(); } // prevent deadlock //@formatter:on meta.insert(o.meta.begin(), o.meta.end()); } template T query(auto &&key) { using Key = decltype(key); auto lock = std::shared_lock(mu); auto iter = meta_map_type::const_iterator(); if constexpr (std::is_convertible_v) { const auto key_hash = (key_type) key; iter = meta.find(key_hash); } else { // const auto key_hash = std::hash()(key); const auto key_hash = std::to_string(key); iter = meta.find(key_hash); } if constexpr (!std::is_same_v) { assert(iter != meta.end()); return boost::any_cast(iter->second); } else { if (iter != meta.end()) { return iter->second; } else { return {}; } } } }; struct meta_proxy { using meta_base_type = meta_base_v2; using meta_key_type = meta_base_type::key_type; using meta_value_type = meta_base_type::value_type; using meta_ptr_type = std::shared_ptr; meta_ptr_type meta; void insert_meta(auto &&key, auto &&value) { get_meta().insert(key, value); } void merge_meta(const meta_proxy &o) { if (o.meta == nullptr) return; get_meta().merge(*o.meta); } template T query_meta(auto &&key) const { if (meta == nullptr) { if constexpr (std::is_same_v) { return {}; } assert(false); } return meta->query(key); } void initialize_meta() { get_meta(); } private: meta_base_type &get_meta() { if (meta == nullptr) [[unlikely]] { meta = std::make_shared(); } return *meta; } }; #endif //META_HELPER_H