LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
thread_safe_registry_via_id.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Provenance_thread_safe_registry_via_id_h
2 #define canvas_Persistency_Provenance_thread_safe_registry_via_id_h
3 
4 // ===================================================================
5 // thread_safe_registry_via_id
6 //
7 // Provides safe access to registry, which never shrinks, but can grow
8 // and be read from multiple threads.
9 //
10 // This DOES NOT prevent reading during a write, nor vice versa. If
11 // one needs to make sure that the contents of the registry are not
12 // changing during a read, then a guard must be placed around the
13 // registry traversal.
14 //
15 // Inefficiencies:
16 //
17 // - To insert pairs from an std::map<K,M> object, one must emplace
18 // each pair one at a time. This seems to be very inefficient;
19 // however, unless we are willing to pay the consequences for
20 // changing the underlying types of some of the persisted objects
21 // that are represented in memory by the below registry, there may
22 // not be a better solution.
23 // ===================================================================
24 
26 #include "tbb/concurrent_unordered_map.h"
27 
28 #include <type_traits>
29 
30 namespace art {
31 
32  namespace detail {
33  template <typename T>
34  struct is_instantiation_of_hash : std::false_type {
35  };
36 
37  template <int I>
38  struct is_instantiation_of_hash<art::Hash<I>> : std::true_type {
39  };
40 
41  template <typename H>
42  struct hash_to_size_t {
43 
45  operator()(H const& id) const
46  {
47  std::ostringstream os;
48  id.print(os);
49  return tbb::tbb_hasher(os.str());
50  }
51  };
52  }
53 
54  template <typename K, typename M>
56  public:
57  using collection_type =
58  tbb::concurrent_unordered_map<K, M, detail::hash_to_size_t<K>>;
59  using value_type = typename collection_type::value_type;
60 
61  template <typename C>
62  static void put(C const& container);
63  static auto emplace(value_type const& value);
64  static auto emplace(K const& key, M const& mapped);
65  static bool empty();
66  static collection_type const& get();
67  static bool get(K const& key, M& mapped);
68 
69  private:
70  static auto&
72  {
73  static collection_type me;
74  return me;
75  }
76  };
77 
78  template <typename K, typename M>
79  template <typename C>
80  void
82  {
83  auto& me = instance();
84  for (auto const& e : container) {
85  me.emplace(e);
86  }
87  }
88 
89  template <typename K, typename M>
90  auto
92  {
93  return instance().emplace(value);
94  }
95 
96  template <typename K, typename M>
97  auto
98  thread_safe_registry_via_id<K, M>::emplace(K const& key, M const& mapped)
99  {
100  return instance().emplace(key, mapped);
101  }
102 
103  template <typename K, typename M>
104  bool
106  {
107  return instance().empty();
108  }
109 
110  template <typename K, typename M>
111  auto
113  {
114  return instance();
115  }
116 
117  template <typename K, typename M>
118  bool
120  {
121  auto& me = instance();
122  auto it = me.find(k);
123  if (it != me.cend()) {
124  mapped = it->second;
125  return true;
126  }
127  return false;
128  }
129 }
130 
131 #endif /* canvas_Persistency_Provenance_thread_safe_registry_via_id_h */
132 
133 // Local Variables:
134 // mode: c++
135 // End:
static void put(C const &container)
typename collection_type::value_type value_type
Double_t K
static collection_type const & get()
tbb::concurrent_unordered_map< K, M, detail::hash_to_size_t< K >> collection_type
std::enable_if_t< is_instantiation_of_hash< H >::value, std::size_t > operator()(H const &id) const
std::string value(boost::any const &)
HLT enums.
Float_t e
Definition: plot.C:34
static auto emplace(value_type const &value)
Definition: Hash.h:32