| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- #ifndef META_HELPER_H
- #define META_HELPER_H
- #include <boost/any.hpp>
- #include <shared_mutex>
- #include <string>
- #include <unordered_map>
- 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<key_type, value_type>;
- 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<Key, key_type>) {
- const auto key_hash = (key_type) key;
- meta[key_hash] = value;
- } else {
- // const auto key_hash = std::hash<Key>()(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<typename T = value_type>
- 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<Key, key_type>) {
- const auto key_hash = (key_type) key;
- iter = meta.find(key_hash);
- } else {
- // const auto key_hash = std::hash<Key>()(key);
- const auto key_hash = std::to_string(key);
- iter = meta.find(key_hash);
- }
- if constexpr (!std::is_same_v<T, value_type>) {
- assert(iter != meta.end());
- return boost::any_cast<T>(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_base_type>;
- 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<typename T = meta_value_type>
- T query_meta(auto &&key) const {
- if (meta == nullptr) {
- if constexpr (std::is_same_v<T, meta_value_type>) {
- return {};
- }
- assert(false);
- }
- return meta->query<T>(key);
- }
- void initialize_meta() {
- get_meta();
- }
- private:
- meta_base_type &get_meta() {
- if (meta == nullptr) [[unlikely]] {
- meta = std::make_shared<meta_base_type>();
- }
- return *meta;
- }
- };
- #endif //META_HELPER_H
|