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 
27 #include <map>
28 #include <mutex>
29 #include <type_traits>
30 
31 namespace art {
32  template <typename K, typename M>
34  public:
35  using collection_type = std::map<K, M>;
36  using value_type = typename collection_type::value_type;
37 
38  template <typename C>
39  static void put(C const& container);
40  static auto emplace(value_type const& value);
41  static auto emplace(K const& key, M const& mapped);
42  static bool empty();
43  static collection_type const& get();
44  static bool get(K const& key, M& mapped);
45  static auto
46  instance(bool cleanup = false)
47  {
48  std::lock_guard sentry{mutex_()};
49  static collection_type* me = new collection_type{};
50  if (cleanup) {
51  delete me;
52  me = nullptr;
53  return me;
54  }
55  if (me == nullptr) {
56  // We have been cleaned up and are now being used again.
57  me = new collection_type{};
58  }
59  return me;
60  }
61 
62  private:
63  static auto&
65  {
66  static std::recursive_mutex m{};
67  return m;
68  }
69  };
70 
71  template <typename K, typename M>
72  template <typename C>
73  void
75  {
76  std::lock_guard sentry{mutex_()};
77  auto me = instance();
78  for (auto const& e : container) {
79  me->emplace(e);
80  }
81  }
82 
83  template <typename K, typename M>
84  auto
86  {
87  std::lock_guard sentry{mutex_()};
88  return instance()->emplace(value);
89  }
90 
91  template <typename K, typename M>
92  auto
94  {
95  std::lock_guard sentry{mutex_()};
96  return instance()->emplace(key, mapped);
97  }
98 
99  template <typename K, typename M>
100  bool
102  {
103  std::lock_guard sentry{mutex_()};
104  return instance()->empty();
105  }
106 
107  template <typename K, typename M>
108  auto
110  {
111  return *instance();
112  }
113 
114  template <typename K, typename M>
115  bool
117  {
118  std::lock_guard sentry{mutex_()};
119  auto me = instance();
120  auto it = me->find(k);
121  if (it != me->cend()) {
122  mapped = it->second;
123  return true;
124  }
125  return false;
126  }
127 }
128 
129 #endif /* canvas_Persistency_Provenance_thread_safe_registry_via_id_h */
130 
131 // Local Variables:
132 // mode: c++
133 // End:
static void put(C const &container)
typename collection_type::value_type value_type
const double e
static collection_type const & get()
static auto instance(bool cleanup=false)
def key(type, name=None)
Definition: graph.py:13
static auto emplace(value_type const &value)