LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
ProviderList.h
Go to the documentation of this file.
1 
18 #ifndef LARCORE_TESTUTILS_PROVIDERLIST_H
19 #define LARCORE_TESTUTILS_PROVIDERLIST_H 1
20 
21 // LArSoft libraries
23 
24 // art libraries
25 #include "cetlib_except/demangle.h"
26 
27 // C/C++ standard libraries
28 #include <memory> // std::unique_ptr()
29 #include <stdexcept> // std::runtime_error
30 #include <typeinfo>
31 #include <unordered_map>
32 #include <utility> // std::forward()
33 
34 namespace testing {
35 
36  namespace details {
37 
40  virtual ~MovableClassWrapperBase() = default;
41 
42  }; // struct MovableClassWrapperBase
43 
59  template <typename T>
61  using datum_t = T;
63  using pointer_t = std::shared_ptr<datum_t>;
64 
65  template <typename U>
66  friend class MovableClassWrapper;
67 
68  public:
69  struct share_t {};
70 
71  static constexpr share_t share = {};
72 
74  MovableClassWrapper() : ptr(std::make_unique<datum_t>()) {}
75 
76  template <typename U>
77  MovableClassWrapper(std::unique_ptr<U>&& from) : ptr(std::move(from))
78  {}
79 
81  MovableClassWrapper(pointer_t&& from) : ptr(std::move(from)) {}
84  {
85  ptr = std::move(from);
86  return *this;
87  }
89 
91  template <typename U>
92  MovableClassWrapper(MovableClassWrapper<U> const& from, share_t) : ptr(from.ptr)
93  {}
94 
96  datum_t& ref() { return *ptr; }
97 
99  datum_t const& ref() const { return *ptr; }
100 
102  datum_t* get() { return ptr.get(); }
103 
105  datum_t const* get() const { return ptr.get(); }
106 
108  bool valid() const { return bool(ptr); }
110 
111  operator bool() const { return valid(); }
113 
114  private:
116 
117  }; // namespace testing
118 
119  } // namespace details
120 
162  class ProviderList {
163  // Sparse implementation notes:
164  // - we use MovableClassWrapperBase in place of std::any because our
165  // providers are recommended to be not copiable
166 
168  template <typename T>
169  using smart_pointer_t = std::unique_ptr<T>;
170 
173 
175  template <typename T>
178  template <typename T>
180 
181  public:
183  struct exception : public std::runtime_error {
184  using std::runtime_error::runtime_error;
185  };
188  using exception::exception;
189  };
191  struct provider_deleted : public exception {
192  using exception::exception;
193  };
195  struct provider_wrong : public exception {
196  using exception::exception;
197  };
198 
214  template <typename T, typename SetupProc, typename... Args>
215  bool custom_setup_instance(std::string label, SetupProc&& provSetup, Args&&... args)
216  {
217  auto k = key<T>(label); // key
218  auto it = data.find(k);
219  if (it != data.end()) return false;
220 
221  pointer_t ptr = std::make_unique<concrete_type_t<T>>(provSetup(std::forward<Args>(args)...));
222  data.emplace_hint(it, std::move(k), std::move(ptr));
223  return true;
224  } // custom_setup_instance()
225 
227  template <typename T, typename SetupProc, typename... Args>
228  bool custom_setup(SetupProc&& provSetup, Args&&... args)
229  {
230  return custom_setup_instance<T, SetupProc, Args...>(
231  "", std::forward<SetupProc>(provSetup), std::forward<Args>(args)...);
232  } // custom_setup()
233 
234  template <typename T, typename... Args>
235  bool setup_instance(std::string label, Args&&... args)
236  {
237  auto k = key<T>(label); // key
238  auto it = data.find(k);
239  if (it != data.end()) return false;
240 
241  pointer_t ptr =
242  std::make_unique<concrete_type_t<T>>(setupProvider<T>(std::forward<Args>(args)...));
243  data.emplace_hint(it, std::move(k), std::move(ptr));
244  return true;
245  } // setup_instance()
246 
248  template <typename T, typename... Args>
249  bool setup(Args&&... args)
250  {
251  return setup_instance<T>("", std::forward<Args>(args)...);
252  }
253 
265  template <typename T>
266  bool acquire(std::unique_ptr<T>&& obj_ptr, std::string label = "")
267  {
268  auto k = key<T>(label); // key
269  auto it = data.find(k);
270  if (it != data.end()) return false;
271 
272  pointer_t ptr = std::make_unique<concrete_type_t<T>>(std::move(obj_ptr));
273  data.emplace_hint(it, std::move(k), std::move(ptr));
274  return true;
275  } // acquire()
276 
285  template <typename T>
286  bool erase(std::string label = "")
287  {
288  auto k = key<T>(label); // key
289  auto target_it = data.find(k);
290  if (target_it == data.end()) return false;
291 
292  // erase this and all the aliases pointing to it
293  auto const* target_ptr = target_it->second.get();
294  auto it = data.begin();
295  while (it != data.end()) {
296  if (it->second.get() == target_ptr)
297  it = data.erase(it);
298  else
299  ++it;
300  } // while
301  return true;
302  } // erase()
303 
305  template <typename Prov, typename Alias>
306  bool set_alias(std::string alias_label = "", std::string prov_label = "")
307  {
308  // find the alias location
309  auto alias_k = key<Alias>(alias_label); // key
310  auto alias_it = data.find(alias_k);
311  if (alias_it != data.end()) return false;
312 
313  // find the original provider location
314  auto prov_elem = get_elem<Prov>(prov_label);
315 
316  // register the shared object to the alias
317  data.emplace_hint(alias_it,
318  std::move(alias_k),
319  std::make_unique<concrete_type_t<Alias>>(
320  prov_elem, typename concrete_type_t<Alias>::share_t()));
321  return true;
322  } // set_alias()
323 
325 
334  template <typename T>
335  T const& get(std::string label = "") const
336  {
337  return get_elem<T>(label).ref();
338  }
339 
340  template <typename T>
341  T& get(std::string label = "")
342  {
343  return get_elem<T>(label).ref();
344  }
346 
348 
357  template <typename T>
358  T const* getPointer(std::string label = "") const
359  {
360  return get_elem<T>(label).get();
361  }
362 
363  template <typename T>
364  T* getPointer(std::string label = "")
365  {
366  return get_elem<T>(label).get();
367  }
369 
371  template <typename T>
372  bool known(std::string label = "") const
373  {
374  return find<T>(label) != data.end();
375  }
376 
378  template <typename T>
379  bool valid(std::string label = "") const
380  {
381  auto it = find<T>(label);
382  return (it != data.end()) && bool(it->second);
383  }
384 
385  private:
386  using key_type = size_t;
387 
388  std::unordered_map<key_type, pointer_t> data;
389 
391  template <typename T>
392  static std::string type_name()
393  {
394  return cet::demangle_symbol(typeid(T).name());
395  }
396 
398  template <typename T>
399  static std::string type_name(T const*)
400  {
401  return type_name<T>();
402  }
403 
406  template <typename T>
407  auto find(std::string label = "") const
408  {
409  return data.find(key<T>(label));
410  }
411 
412  template <typename T>
413  auto find(std::string label = "")
414  {
415  return data.find(key<T>(label));
416  }
418 
419  template <typename T>
420  concrete_type_t<T> const& get_elem(std::string label = "") const
421  {
422  auto it = find<T>(label);
423  if (it == data.end()) throw provider_not_available("Not available: " + type_name<T>());
424  if (!(it->second)) throw provider_deleted("Deleted: " + type_name<T>());
425  auto* ptr = dynamic_cast<details::MovableClassWrapper<T>*>(it->second.get());
426  if (!ptr) {
427  throw provider_wrong("Wrong: " + type_name(it->second.get()) +
428  " [requested: " + type_name<T>() + "]");
429  }
430  return *ptr;
431  } // get_elem()
432 
433  template <typename T>
434  concrete_type_t<T>& get_elem(std::string label = "")
435  {
436  auto it = find<T>(label);
437  if (it == data.end()) throw provider_not_available("Not available: " + type_name<T>());
438  if (!(it->second)) throw provider_deleted("Deleted: " + type_name<T>());
439  auto* ptr = dynamic_cast<details::MovableClassWrapper<T>*>(it->second.get());
440  if (!ptr) {
441  throw provider_wrong("Wrong: " + type_name(it->second.get()) +
442  " [requested: " + type_name<T>() + "]");
443  }
444  return *ptr;
445  } // get_elem()
446 
448  template <typename T>
449  static key_type key(std::string label = "")
450  {
451  return typeid(std::decay_t<T>).hash_code() ^ std::hash<std::string>()(label);
452  }
453 
454  }; // class ProviderList
455 
456 } // namespace testing
457 
458 #endif // LARCORE_TESTUTILS_PROVIDERLIST_H
smart_pointer_t< details::MovableClassWrapperBase > pointer_t
Type of objects contained in the list.
Definition: ProviderList.h:172
Container of service providers accessed by type and optional label.
Definition: ProviderList.h:162
LArSoft test utilities.
T const * getPointer(std::string label="") const
Retrieve the object of type T stored with the specified label.
Definition: ProviderList.h:358
MovableClassWrapper(MovableClassWrapper< U > const &from, share_t)
Share constructor (kind of copy)
Definition: ProviderList.h:92
Helper classes to be used together with LArSoft&#39;s unit test.
Exception thrown on a request about an unregistered type.
Definition: ProviderList.h:187
concrete_type_t< T > & get_elem(std::string label="")
Definition: ProviderList.h:434
Exception thrown on a invalid type request.
Definition: ProviderList.h:195
MovableClassWrapper(std::unique_ptr< U > &&from)
Definition: ProviderList.h:77
datum_t const & ref() const
Returns a constant reference to the datum with the correct type.
Definition: ProviderList.h:99
static std::string type_name(T const *)
Convert a pointer to object into a demangled type name.
Definition: ProviderList.h:399
bool known(std::string label="") const
Returns whether we have a slot for this object.
Definition: ProviderList.h:372
STL namespace.
std::unique_ptr< T > smart_pointer_t
type of smart pointer we use to store elements
Definition: ProviderList.h:169
bool setup_instance(std::string label, Args &&...args)
Definition: ProviderList.h:235
MovableClassWrapper()
Default constructor: no datum present (move one in later on)
Definition: ProviderList.h:74
smart_pointer_t< concrete_type_t< T >> concrete_pointer_t
Type of smart pointer to typed list element.
Definition: ProviderList.h:179
datum_t & ref()
Returns a reference to the datum with the correct type.
Definition: ProviderList.h:96
bool acquire(std::unique_ptr< T > &&obj_ptr, std::string label="")
Registers and gets ownership of the specified object.
Definition: ProviderList.h:266
MovableClassWrapper & operator=(pointer_t &&from)
Constructor and assignment from a unique pointer: steal the content.
Definition: ProviderList.h:83
bool erase(std::string label="")
Drops the object with the specified type and label.
Definition: ProviderList.h:286
concrete_type_t< T > const & get_elem(std::string label="") const
Definition: ProviderList.h:420
A base class with a virtual table.
Definition: ProviderList.h:39
std::shared_ptr< datum_t > pointer_t
pointer storing datum
Definition: ProviderList.h:63
bool set_alias(std::string alias_label="", std::string prov_label="")
Sets the Alias type as an alias of the Prov provider (with labels)
Definition: ProviderList.h:306
bool custom_setup_instance(std::string label, SetupProc &&provSetup, Args &&...args)
Construct and register an object of type T.
Definition: ProviderList.h:215
T * getPointer(std::string label="")
Retrieve the object of type T stored with the specified label.
Definition: ProviderList.h:364
bool valid(std::string label="") const
Returns whether the specified object is available.
Definition: ProviderList.h:379
bool custom_setup(SetupProc &&provSetup, Args &&...args)
Construct and register an object of type T with specified arguments.
Definition: ProviderList.h:228
base exception class for ProviderList
Definition: ProviderList.h:183
bool setup(Args &&...args)
Construct and register an object of type T with specified arguments.
Definition: ProviderList.h:249
Exception thrown on when object is not available any more.
Definition: ProviderList.h:191
auto find(std::string label="")
Definition: ProviderList.h:413
auto find(std::string label="") const
Definition: ProviderList.h:407
static key_type key(std::string label="")
Extracts and returns the key out of a type and label.
Definition: ProviderList.h:449
std::unordered_map< key_type, pointer_t > data
all our singletons
Definition: ProviderList.h:388
static std::string type_name()
Convert a type into a demangled type name.
Definition: ProviderList.h:392
A class containing an owned object.
Definition: ProviderList.h:60
size_t key_type
type used for key in the internal registry
Definition: ProviderList.h:386
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33