LArSoft  v07_13_02
Liquid Argon Software toolkit - http://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 <unordered_map>
26 #include <memory> // std::unique_ptr()
27 #include <utility> // std::forward()
28 #include <typeinfo>
29 
30 
31 
32 namespace testing {
33 
34  namespace details {
35 
38  virtual ~MovableClassWrapperBase() = default;
39 
40  }; // struct MovableClassWrapperBase
41 
57  template <typename T>
59  using datum_t = T;
61  using pointer_t = std::shared_ptr<datum_t>;
62 
63 
64  template<typename U>
65  friend class MovableClassWrapper;
66 
67  public:
68  struct share_t {};
69 
70  static constexpr share_t share = {};
71 
73  MovableClassWrapper(): ptr(std::make_unique<datum_t>()) {}
74 
75  template <typename U>
76  MovableClassWrapper(std::unique_ptr<U>&& from): ptr(std::move(from)) {}
77 
79  MovableClassWrapper(pointer_t&& from): ptr(std::move(from)) {}
81  MovableClassWrapper& operator= (pointer_t&& from)
82  { ptr = std::move(from); return *this; }
84 
86  template<typename U>
88  ptr(from.ptr) {}
89 
90 
92  datum_t& ref() { return *ptr; }
93 
95  datum_t const& ref() const { return *ptr; }
96 
98  datum_t* get() { return ptr.get(); }
99 
101  datum_t const* get() const { return ptr.get(); }
102 
104  bool valid() const { return bool(ptr); }
106 
107  operator bool() const { return valid(); }
109 
110  private:
112 
113  }; // namespace testing
114 
115  } // namespace details
116 
117 
118 
160  class ProviderList {
161  // Sparse implementation notes:
162  // - we use MovableClassWrapperBase in place of boost::any because our
163  // providers are recommended to be not copiable
164 
166  template <typename T>
167  using smart_pointer_t = std::unique_ptr<T>;
168 
171 
173  template <typename T>
176  template <typename T>
178 
179  public:
181  struct exception: public std::runtime_error
182  { using std::runtime_error::runtime_error; };
185  { using exception::exception; };
188  { using exception::exception; };
190  struct provider_wrong: public exception
191  { using exception::exception; };
192 
193 
209  template <typename T, typename SetupProc, typename... Args>
210  bool custom_setup_instance
211  (std::string label, SetupProc&& provSetup, Args&&... args)
212  {
213  auto k = key<T>(label); // key
214  auto it = data.find(k);
215  if (it != data.end()) return false;
216 
217  pointer_t ptr = std::make_unique<concrete_type_t<T>>
218  (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  "",
229  std::forward<SetupProc>(provSetup),
230  std::forward<Args>(args)...
231  );
232  } // custom_setup()
233 
234  template <typename T, typename... Args>
235  bool setup_instance
236  (std::string label, Args&&... args)
237  {
238  auto k = key<T>(label); // key
239  auto it = data.find(k);
240  if (it != data.end()) return false;
241 
242  pointer_t ptr = std::make_unique<concrete_type_t<T>>
243  (setupProvider<T>(std::forward<Args>(args)...));
244  data.emplace_hint(it, std::move(k), std::move(ptr));
245  return true;
246  // return custom_setup_instance<T>
247  // (label, setupProvider<T, Args...>, std::forward<Args>(args)...);
248  } // setup_instance()
249 
251  template <typename T, typename... Args>
252  bool setup(Args&&... args)
253  { return setup_instance<T>("", std::forward<Args>(args)...); }
254 
255 
267  template <typename T>
268  bool acquire(std::unique_ptr<T>&& obj_ptr, std::string label = "")
269  {
270  auto k = key<T>(label); // key
271  auto it = data.find(k);
272  if (it != data.end()) return false;
273 
274  pointer_t ptr
275  = std::make_unique<concrete_type_t<T>>(std::move(obj_ptr));
276  data.emplace_hint(it, std::move(k), std::move(ptr));
277  return true;
278  } // acquire()
279 
280 
289  template <typename T>
290  bool erase(std::string label = "")
291  {
292  auto k = key<T>(label); // key
293  auto target_it = data.find(k);
294  if (target_it == data.end()) return false;
295 
296  // erase this and all the aliases pointing to it
297  auto const* target_ptr = target_it->second.get();
298  auto it = data.begin();
299  while (it != data.end()) {
300  if (it->second.get() == target_ptr) it = data.erase(it);
301  else ++it;
302  } // while
303  return true;
304  } // erase()
305 
306 
308  template <typename Prov, typename Alias>
309  bool set_alias(std::string alias_label = "", std::string prov_label = "")
310  {
311  // find the alias location
312  auto alias_k = key<Alias>(alias_label); // key
313  auto alias_it = data.find(alias_k);
314  if (alias_it != data.end()) return false;
315 
316  // find the original provider location
317  auto prov_elem = get_elem<Prov>(prov_label);
318 
319  // register the shared object to the alias
320  data.emplace_hint(alias_it, std::move(alias_k),
321  std::make_unique<concrete_type_t<Alias>>
322  (prov_elem, typename concrete_type_t<Alias>::share_t())
323  );
324  return true;
325  } // set_alias()
326 
327 
329 
338  template <typename T>
339  T const& get(std::string label = "") const
340  { return get_elem<T>(label).ref(); }
341 
342  template <typename T>
343  T& get(std::string label = "")
344  { return get_elem<T>(label).ref(); }
346 
348 
357  template <typename T>
358  T const* getPointer(std::string label = "") const
359  { return get_elem<T>(label).get(); }
360 
361  template <typename T>
362  T* getPointer(std::string label = "")
363  { return get_elem<T>(label).get(); }
365 
367  template <typename T>
368  bool known(std::string label = "") const
369  { return find<T>(label) != data.end(); }
370 
372  template <typename T>
373  bool valid(std::string label = "") const
374  {
375  auto it = find<T>(label);
376  return (it != data.end()) && bool(it->second);
377  }
378 
379  private:
380  using key_type = size_t;
381 
382  std::unordered_map<key_type, pointer_t> data;
383 
385  template <typename T>
386  static std::string type_name() { return typeid(T).name(); }
387 
389  template <typename T>
390  static std::string type_name(T const* ptr) { return typeid(*ptr).name(); }
391 
394  template <typename T>
395  auto find(std::string label = "") const
396  { return data.find(key<T>(label)); }
397 
398  template <typename T>
399  auto find(std::string label = "") { return data.find(key<T>(label)); }
401 
402  template <typename T>
403  concrete_type_t<T> const& get_elem(std::string label = "") const
404  {
405  auto it = find<T>(label);
406  if (it == data.end())
407  throw provider_not_available("Not available: " + type_name<T>());
408  if (!(it->second))
409  throw provider_deleted("Deleted: " + type_name<T>());
410  auto* ptr = dynamic_cast<details::MovableClassWrapper<T>*>
411  (it->second.get());
412  if (!ptr) {
413  throw provider_wrong("Wrong: " + type_name(it->second.get())
414  + " [requested: " + type_name<T>() + "]");
415  }
416  return *ptr;
417  } // get_elem()
418 
419  template <typename T>
420  concrete_type_t<T>& get_elem(std::string label = "")
421  {
422  auto it = find<T>(label);
423  if (it == data.end())
424  throw provider_not_available("Not available: " + type_name<T>());
425  if (!(it->second))
426  throw provider_deleted("Deleted: " + type_name<T>());
427  auto* ptr = dynamic_cast<details::MovableClassWrapper<T>*>
428  (it->second.get());
429  if (!ptr) {
430  throw provider_wrong("Wrong: " + type_name(it->second.get())
431  + " [requested: " + type_name<T>() + "]");
432  }
433  return *ptr;
434  } // get_elem()
435 
437  template <typename T>
438  static key_type key(std::string label = "")
439  {
440  return typeid(std::decay_t<T>).hash_code()
441  ^ std::hash<std::string>()(label);
442  }
443 
444  }; // class ProviderList
445 
446 
447 } // namespace testing
448 
449 
450 
451 #endif // LARCORE_TESTUTILS_PROVIDERLIST_H
smart_pointer_t< details::MovableClassWrapperBase > pointer_t
Type of objects contained in the list.
Definition: ProviderList.h:170
Container of service providers accessed by type and optional label.
Definition: ProviderList.h:160
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:87
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:420
Exception thrown on a invalid type request.
Definition: ProviderList.h:190
MovableClassWrapper(std::unique_ptr< U > &&from)
Definition: ProviderList.h:76
datum_t const & ref() const
Returns a constant reference to the datum with the correct type.
Definition: ProviderList.h:95
bool known(std::string label="") const
Returns whether we have a slot for this object.
Definition: ProviderList.h:368
STL namespace.
std::unique_ptr< T > smart_pointer_t
type of smart pointer we use to store elements
Definition: ProviderList.h:167
MovableClassWrapper()
Default constructor: no datum present (move one in later on)
Definition: ProviderList.h:73
smart_pointer_t< concrete_type_t< T >> concrete_pointer_t
Type of smart pointer to typed list element.
Definition: ProviderList.h:177
datum_t & ref()
Returns a reference to the datum with the correct type.
Definition: ProviderList.h:92
bool acquire(std::unique_ptr< T > &&obj_ptr, std::string label="")
Registers and gets ownership of the specified object.
Definition: ProviderList.h:268
bool erase(std::string label="")
Drops the object with the specified type and label.
Definition: ProviderList.h:290
concrete_type_t< T > const & get_elem(std::string label="") const
Definition: ProviderList.h:403
A base class with a virtual table.
Definition: ProviderList.h:37
std::shared_ptr< datum_t > pointer_t
pointer storing datum
Definition: ProviderList.h:61
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:309
T * getPointer(std::string label="")
Retrieve the object of type T stored with the specified label.
Definition: ProviderList.h:362
static std::string type_name(T const *ptr)
Convert a pointer to object into a (ugly) type name.
Definition: ProviderList.h:390
bool valid(std::string label="") const
Returns whether the specified object is available.
Definition: ProviderList.h:373
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:181
bool setup(Args &&...args)
Construct and register an object of type T with specified arguments.
Definition: ProviderList.h:252
Exception thrown on when object is not available any more.
Definition: ProviderList.h:187
auto find(std::string label="")
Definition: ProviderList.h:399
auto find(std::string label="") const
Definition: ProviderList.h:395
static key_type key(std::string label="")
Extracts and returns the key out of a type and label.
Definition: ProviderList.h:438
std::unordered_map< key_type, pointer_t > data
all our singletons
Definition: ProviderList.h:382
static std::string type_name()
Convert a type into a (ugly) type name.
Definition: ProviderList.h:386
A class containing an owned object.
Definition: ProviderList.h:58
size_t key_type
type used for key in the internal registry
Definition: ProviderList.h:380
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33