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