meta_helper.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #ifndef META_HELPER_H
  2. #define META_HELPER_H
  3. #include <boost/any.hpp>
  4. #include <shared_mutex>
  5. #include <string>
  6. #include <unordered_map>
  7. struct meta_base_v2 {
  8. // using key_type = std::size_t;
  9. using key_type = std::string;
  10. using value_type = boost::any;
  11. using meta_map_type = std::unordered_map<key_type, value_type>;
  12. meta_map_type meta;
  13. std::shared_mutex mu;
  14. void insert(auto &&key, const value_type &value) {
  15. using Key = decltype(key);
  16. auto lock = std::unique_lock(mu);
  17. if constexpr (std::is_convertible_v<Key, key_type>) {
  18. const auto key_hash = (key_type) key;
  19. meta[key_hash] = value;
  20. } else {
  21. // const auto key_hash = std::hash<Key>()(key);
  22. const auto key_hash = std::to_string(key);
  23. meta[key_hash] = value;
  24. }
  25. }
  26. void merge(meta_base_v2 &o) {
  27. if (this == &o) return;
  28. //@formatter:off
  29. auto read_lock = std::shared_lock(o.mu, std::defer_lock);
  30. auto write_lock = std::unique_lock(mu, std::defer_lock);
  31. assert(&o.mu != &mu);
  32. if (&o.mu < &mu) { read_lock.lock(); write_lock.lock(); }
  33. else { write_lock.lock(); read_lock.lock(); } // prevent deadlock
  34. //@formatter:on
  35. meta.insert(o.meta.begin(), o.meta.end());
  36. }
  37. template<typename T = value_type>
  38. T query(auto &&key) {
  39. using Key = decltype(key);
  40. auto lock = std::shared_lock(mu);
  41. auto iter = meta_map_type::const_iterator();
  42. if constexpr (std::is_convertible_v<Key, key_type>) {
  43. const auto key_hash = (key_type) key;
  44. iter = meta.find(key_hash);
  45. } else {
  46. // const auto key_hash = std::hash<Key>()(key);
  47. const auto key_hash = std::to_string(key);
  48. iter = meta.find(key_hash);
  49. }
  50. if constexpr (!std::is_same_v<T, value_type>) {
  51. assert(iter != meta.end());
  52. return boost::any_cast<T>(iter->second);
  53. } else {
  54. if (iter != meta.end()) {
  55. return iter->second;
  56. } else {
  57. return {};
  58. }
  59. }
  60. }
  61. };
  62. struct meta_proxy {
  63. using meta_base_type = meta_base_v2;
  64. using meta_key_type = meta_base_type::key_type;
  65. using meta_value_type = meta_base_type::value_type;
  66. using meta_ptr_type = std::shared_ptr<meta_base_type>;
  67. meta_ptr_type meta;
  68. void insert_meta(auto &&key, auto &&value) {
  69. get_meta().insert(key, value);
  70. }
  71. void merge_meta(const meta_proxy &o) {
  72. if (o.meta == nullptr) return;
  73. get_meta().merge(*o.meta);
  74. }
  75. template<typename T = meta_value_type>
  76. T query_meta(auto &&key) const {
  77. if (meta == nullptr) {
  78. if constexpr (std::is_same_v<T, meta_value_type>) {
  79. return {};
  80. }
  81. assert(false);
  82. }
  83. return meta->query<T>(key);
  84. }
  85. void initialize_meta() {
  86. get_meta();
  87. }
  88. private:
  89. meta_base_type &get_meta() {
  90. if (meta == nullptr) [[unlikely]] {
  91. meta = std::make_shared<meta_base_type>();
  92. }
  93. return *meta;
  94. }
  95. };
  96. #endif //META_HELPER_H