https://mooseframework.inl.gov
TheWarehouse.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #pragma once
11 
12 #include <map>
13 #include <string>
14 #include <vector>
15 #include <unordered_map>
16 #include <iostream>
17 #include <mutex>
18 #include <type_traits>
19 
20 #include "MooseObject.h"
21 #include "MooseHashing.h"
22 #include "MooseUtils.h"
23 
24 class MooseObject;
25 class WarehouseStorage;
26 class TheWarehouse;
27 
51 class Attribute
52 {
53 public:
56  Attribute(TheWarehouse & w, const std::string name);
57  virtual ~Attribute() {}
58 
59  inline bool operator==(const Attribute & other) const
60  {
61  return _id == other._id && isEqual(other);
62  }
63  inline bool operator!=(const Attribute & other) const { return !(*this == other); }
64 
68  inline unsigned int id() const { return _id; }
69 
76  virtual std::size_t hash() const = 0;
77 
79  virtual void initFrom(const MooseObject * obj) = 0;
83  virtual bool isMatch(const Attribute & other) const = 0;
87  virtual bool isEqual(const Attribute & other) const = 0;
90  virtual std::unique_ptr<Attribute> clone() const = 0;
91 
92 private:
93  int _id = -1;
94 };
95 
96 #define clonefunc(T) \
97  virtual std::unique_ptr<Attribute> clone() const override \
98  { \
99  return std::unique_ptr<Attribute>(new T(*this)); \
100  }
101 
102 #define hashfunc(...) \
103  virtual std::size_t hash() const override \
104  { \
105  std::size_t h = 0; \
106  Moose::hash_combine(h, __VA_ARGS__); \
107  return h; \
108  }
109 
113 class AttribSorted : public Attribute
114 {
115 public:
116  typedef bool Key;
117  void setFrom(const Key & k) { _val = k; }
118 
119  AttribSorted(TheWarehouse & w) : Attribute(w, "sorted"), _val(false), _initd(false) {}
121  : Attribute(w, "sorted"), _val(is_sorted), _initd(true)
122  {
123  }
124  AttribSorted(const AttribSorted &) = default;
125  AttribSorted(AttribSorted &&) = default;
126  AttribSorted & operator=(const AttribSorted &) = default;
127  AttribSorted & operator=(AttribSorted &&) = default;
128 
129  virtual void initFrom(const MooseObject * obj) override;
130  virtual bool isMatch(const Attribute & other) const override;
131  virtual bool isEqual(const Attribute & other) const override;
132  hashfunc(_val);
134 
135 private:
136  bool _val;
137  bool _initd;
138 };
139 
140 #undef clonefunc
141 #undef hashfunc
142 
145 bool operator==(const std::unique_ptr<Attribute> & lhs, const std::unique_ptr<Attribute> & rhs);
146 
147 namespace std
148 {
150 template <>
151 struct hash<Attribute>
152 {
153 public:
154  std::size_t operator()(const Attribute & attrib) const
155  {
156  std::size_t h = attrib.hash();
157  Moose::hash_combine(h, attrib.id());
158  return h;
159  }
160 };
161 
163 template <>
164 struct hash<std::vector<std::unique_ptr<Attribute>>>
165 {
166 public:
167  std::size_t operator()(const std::vector<std::unique_ptr<Attribute>> & attribs) const
168  {
169  std::size_t h = 0;
170  for (auto & attrib : attribs)
171  Moose::hash_combine(h, *attrib);
172  return h;
173  }
174 };
175 }
176 
187 {
188 public:
189  template <typename T>
190  using KeyType = typename T::Key;
191  template <typename T>
192  using AttribType = T *;
193 
208  template <typename... Attribs>
210  {
211  public:
212  typedef std::tuple<KeyType<Attribs>...> KeyTuple;
213  typedef std::tuple<AttribType<Attribs>...> AttribTuple;
214 
216 
220  {
221  addAttribs<0, Attribs...>();
222  _attribs.reserve(5);
223  }
224 
225  template <typename T>
226  QueryCache(const T & q) : _w(&q.warehouse())
227  {
228  addAttribs<0, Attribs...>();
229  _attribs.reserve(5);
230 
231  for (auto & attrib : q.attributes())
232  _attribs.push_back(attrib->clone());
233  }
234 
235  QueryCache & operator=(const QueryCache & other)
236  {
237  if (this == &other)
238  return *this;
239 
240  _attribs.clear();
241  _w = other._w;
242  // MUST have own pointers to attribs to avoid data races - don't copy _key_attribs.
243  // initialize parametrized attributes and tuple:
244  addAttribs<0, Attribs...>();
245  _key_tup = other._key_tup;
246  // do NOT copy the cache.
247 
248  // only copy over non-parametrized attributes
249  for (std::size_t i = std::tuple_size<AttribTuple>::value; i < other._attribs.size(); i++)
250  _attribs.push_back(other._attribs[i]->clone());
251  return *this;
252  }
253 
255  template <typename T>
256  QueryCache & operator=(const T & q)
257  {
258  _attribs.clear();
259  _w = &q.warehouse();
260 
261  addAttribs<0, Attribs...>();
262  _attribs.reserve(5);
263 
264  for (auto & attrib : q.attributes())
265  _attribs.push_back(attrib->clone());
266 
267  return *this;
268  }
269 
270  QueryCache(const QueryCache & other) : _w(other._w), _key_tup(other._key_tup)
271  {
272  // do NOT copy the cache.
273 
274  // initialize parametrized attributes and tuple:
275  addAttribs<0, Attribs...>(); // MUST have own pointers to attribs to avoid data races.
276  for (std::size_t i = std::tuple_size<AttribTuple>::value; i < other._attribs.size(); i++)
277  _attribs.push_back(other._attribs[i]->clone());
278  }
279 
284  template <typename T, typename... Args>
285  QueryCache & condition(Args &&... args)
286  {
287  _attribs.emplace_back(new T(*_w, std::forward<Args>(args)...));
288  _cache.clear(); // invalidate cache if base query changes.
289  return *this;
290  }
291 
293  QueryCache clone() const { return Query(*this); }
296  std::size_t count() { return _w->count(_attribs); }
297 
298  TheWarehouse & warehouse() const { return *_w; }
299 
301  std::vector<std::unique_ptr<Attribute>> attributes() const { return clone()._attribs; }
302 
311  template <typename T, typename... Args>
312  std::vector<T *> & queryInto(std::vector<T *> & results, Args &&... args)
313  {
314  return queryIntoHelper(results, true, args...);
315  }
316 
324  template <typename T, typename... Args>
325  std::vector<T *> & queryIntoUnsorted(std::vector<T *> & results, Args &&... args)
326  {
327  return queryIntoHelper(results, false, args...);
328  }
329 
331  std::size_t numAttribs() const { return _attribs.size(); }
332 
333  private:
342  template <typename T, typename... Args>
343  std::vector<T *> & queryIntoHelper(std::vector<T *> & results, const bool sort, Args &&... args)
344  {
345  std::lock_guard<std::mutex> lock(_cache_mutex);
346  setKeysInner<0, KeyType<Attribs>...>(args...);
347 
348  std::size_t query_id;
349  const auto entry = _cache.find(std::make_pair(sort, _key_tup));
350  if (entry == _cache.end())
351  {
352  setAttribsInner<0, KeyType<Attribs>...>(args...);
353  // add the sort attribute. No need (I think) to clear the cache because the base query is
354  // not changing
355  _attribs.emplace_back(new AttribSorted(*_w, sort));
356  query_id = _w->queryID(_attribs);
357  _cache[std::make_pair(sort, _key_tup)] = query_id;
358  // remove the sort attribute
359  _attribs.pop_back();
360  }
361  else
362  query_id = entry->second;
363 
364  return _w->queryInto(query_id, results);
365  }
366 
367  template <int Index, typename A, typename... As>
368  void addAttribs()
369  {
370  std::get<Index>(_attrib_tup) = new A(*_w);
371  _attribs.emplace_back(std::get<Index>(_attrib_tup));
372  addAttribs<Index + 1, As...>();
373  }
374  template <int Index>
375  void addAttribs()
376  {
377  }
378 
379  template <int Index, typename K, typename... Args>
380  void setKeysInner(K & k, Args &... args)
381  {
382  std::get<Index>(_key_tup) = k;
383  setKeysInner<Index + 1, Args...>(args...);
384  }
385  template <int Index>
387  {
388  }
389 
390  template <int Index, typename K, typename... Args>
391  void setAttribsInner(K k, Args &... args)
392  {
393  std::get<Index>(_attrib_tup)->setFrom(k);
394  setAttribsInner<Index + 1, Args...>(args...);
395  }
396  template <int Index>
398  {
399  }
400 
401  TheWarehouse * _w = nullptr;
402  std::vector<std::unique_ptr<Attribute>> _attribs;
403 
406  std::map<std::pair<bool, KeyTuple>, std::size_t> _cache;
407  std::mutex _cache_mutex;
408  };
409 
411 
412  TheWarehouse();
413  ~TheWarehouse();
414 
429  template <typename T, typename... Args>
430  unsigned int registerAttribute(const std::string & name, Args... dummy_args)
431  {
432  auto it = _attrib_ids.find(name);
433  if (it != _attrib_ids.end())
434  return it->second;
435 
436  _attrib_ids[name] = _attrib_list.size();
437  _attrib_list.push_back(std::unique_ptr<Attribute>(new T(*this, dummy_args...)));
438  return _attrib_list.size() - 1;
439  }
440 
444  inline unsigned int attribID(const std::string & name)
445  {
446  auto it = _attrib_ids.find(name);
447  if (it != _attrib_ids.end())
448  return it->second;
449  mooseError("no ID exists for unregistered attribute '", name, "'");
450  }
451 
454  void add(std::shared_ptr<MooseObject> obj);
455 
459  void update(MooseObject * obj);
464  void update(MooseObject * obj, const Attribute & extra);
467  Query query() { return Query(*this); }
471  std::size_t count(const std::vector<std::unique_ptr<Attribute>> & conds);
477  template <typename T>
478  std::vector<T *> & queryInto(const std::vector<std::unique_ptr<Attribute>> & conds,
479  std::vector<T *> & results)
480  {
481  return queryInto(queryID(conds), results);
482  }
483 
484  std::size_t queryID(const std::vector<std::unique_ptr<Attribute>> & conds);
485 
486  template <typename T>
487  std::vector<T *> & queryInto(int query_id, std::vector<T *> & results, bool show_all = false)
488  {
489  std::lock_guard<std::mutex> lock(_obj_cache_mutex);
490  auto & objs = query(query_id);
491  results.clear();
492  results.reserve(objs.size());
493  for (auto & obj : objs)
494  {
495  mooseAssert(obj, "Null object");
496  T * cast_obj;
497  // We've been using dynamic_cast plus an assert that it
498  // succeeds, but if we know the correct type T then often we can
499  // use a much-cheaper static_cast. libMesh::cast_ptr will still
500  // use a dynamic_cast + assertion in devel/dbg modes.
501  if constexpr (std::is_convertible_v<MooseObject *, std::remove_cv_t<T> *> ||
502  std::is_convertible_v<std::remove_cv_t<T> *, MooseObject *>)
503  {
504  cast_obj = cast_ptr<T *>(obj);
505  }
506  // Side-casts or virtual inheritence are always expensive.
507  // Someone should figure out how to get rid of this code path.
508  else
509  {
510  cast_obj = dynamic_cast<T *>(obj);
511  mooseAssert(cast_obj,
512  "Queried object " + obj->typeAndName() + " has incompatible c++ type with " +
513  MooseUtils::prettyCppType<T>());
514  }
515 
516  mooseAssert(std::find(results.begin(), results.end(), cast_obj) == results.end(),
517  "Duplicate object");
518  if (show_all || obj->enabled())
519  results.push_back(cast_obj);
520  }
521  return results;
522  }
523 
524 private:
526  int prepare(std::vector<std::unique_ptr<Attribute>> conds);
527 
530  const std::vector<MooseObject *> & query(int query_id);
531 
532  void readAttribs(const MooseObject * obj, std::vector<std::unique_ptr<Attribute>> & attribs);
533 
534  std::unique_ptr<WarehouseStorage> _store;
535  std::vector<std::shared_ptr<MooseObject>> _objects;
536  std::unordered_map<MooseObject *, std::size_t> _obj_ids;
537 
538  // Results from queries are cached here. The outer vector index is the query id as stored by the
539  // _query_cache data structure. A list objects that match each query id are stored.
540  std::vector<std::vector<MooseObject *>> _obj_cache;
541  // This stores a query id for every query keyed by the query conditions/attributes.
542  // User-initiated queries check this map to see if a queries results have already been cached.
543  // The query id is an index into the _obj_cache data structure.
544  std::unordered_map<std::vector<std::unique_ptr<Attribute>>, int> _query_cache;
545 
546  std::unordered_map<std::string, unsigned int> _attrib_ids;
547  std::vector<std::unique_ptr<Attribute>> _attrib_list;
548 
549  std::mutex _obj_mutex;
550  std::mutex _query_cache_mutex;
551  std::mutex _obj_cache_mutex;
552 };
std::string name(const ElemQuality q)
unsigned int id() const
returns the unique attribute ID associated with all attributes that have the same (mose derived) clas...
Definition: TheWarehouse.h:68
std::mutex _obj_cache_mutex
Definition: TheWarehouse.h:551
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
std::size_t count(const std::vector< std::unique_ptr< Attribute >> &conds)
count returns the number of objects that match the provided query conditions.
Definition: TheWarehouse.C:270
std::vector< T * > & queryIntoHelper(std::vector< T *> &results, const bool sort, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Definition: TheWarehouse.h:343
QueryCache is a convenient way to construct and pass around (possible partially constructed) warehous...
Definition: TheWarehouse.h:209
bool operator!=(const Attribute &other) const
Definition: TheWarehouse.h:63
Attribute is an abstract class that can be implemented in order to track custom metadata about MooseO...
Definition: TheWarehouse.h:51
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
void add(std::shared_ptr< MooseObject > obj)
add adds a new object to the warehouse and stores attributes/metadata about it for running queries/fi...
Definition: TheWarehouse.C:116
std::vector< T * > & queryInto(std::vector< T *> &results, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Definition: TheWarehouse.h:312
virtual bool isEqual(const Attribute &other) const =0
isEqual returns true if the meta-data stored in this attribute is identical to that stored in other...
This attribute describes sorting state.
Definition: TheWarehouse.h:113
QueryCache(const QueryCache &other)
Definition: TheWarehouse.h:270
bool operator==(const Attribute &other) const
Definition: TheWarehouse.h:59
std::tuple< KeyType< Attribs >... > KeyTuple
Definition: TheWarehouse.h:212
Attribute(TheWarehouse &w, const std::string name)
Constructs/initializes a new attribute with the specified name for use in warehouse w...
Definition: TheWarehouse.C:36
void hash_combine(std::size_t &)
Used for hash function specialization for Attribute objects.
Definition: MooseHashing.h:22
std::size_t count()
count returns the number of results that match the query (this requires actually running the query)...
Definition: TheWarehouse.h:296
QueryCache(TheWarehouse &w)
Creates a new query operating on the given warehouse w.
Definition: TheWarehouse.h:219
virtual std::size_t hash() const =0
This function must return a deterministic value that is uniquely determined by the data the attribute...
virtual bool isEqual(const Attribute &other) const override
isEqual returns true if the meta-data stored in this attribute is identical to that stored in other...
Definition: TheWarehouse.C:51
std::size_t operator()(const Attribute &attrib) const
Definition: TheWarehouse.h:154
std::vector< std::unique_ptr< Attribute > > _attribs
Definition: TheWarehouse.h:402
std::unique_ptr< WarehouseStorage > _store
Definition: TheWarehouse.h:534
void setAttribsInner(K k, Args &... args)
Definition: TheWarehouse.h:391
std::unordered_map< std::string, unsigned int > _attrib_ids
Definition: TheWarehouse.h:546
QueryCache & operator=(const T &q)
Copy constructor from another Query.
Definition: TheWarehouse.h:256
std::mutex _query_cache_mutex
Definition: TheWarehouse.h:550
QueryCache<> Query
Definition: TheWarehouse.h:410
std::map< std::pair< bool, KeyTuple >, std::size_t > _cache
Definition: TheWarehouse.h:406
bool operator==(const std::unique_ptr< Attribute > &lhs, const std::unique_ptr< Attribute > &rhs)
TheWarehouse uses this operator function for indexing and caching queries.
Definition: TheWarehouse.C:31
std::vector< std::shared_ptr< MooseObject > > _objects
Definition: TheWarehouse.h:535
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:28
std::size_t numAttribs() const
Gets the number of attributes associated with the cached query.
Definition: TheWarehouse.h:331
QueryCache & operator=(const QueryCache &other)
Definition: TheWarehouse.h:235
void readAttribs(const MooseObject *obj, std::vector< std::unique_ptr< Attribute >> &attribs)
Definition: TheWarehouse.C:283
TheWarehouse & warehouse() const
Definition: TheWarehouse.h:298
std::size_t queryID(const std::vector< std::unique_ptr< Attribute >> &conds)
Definition: TheWarehouse.C:253
TheWarehouse is a container for MooseObjects that allows querying/filtering over various customizeabl...
Definition: TheWarehouse.h:186
virtual bool isMatch(const Attribute &other) const override
isMatch returns true if the meta-data stored in this attribute is equivalent to that stored in other...
Definition: TheWarehouse.C:44
std::vector< T * > & queryInto(int query_id, std::vector< T *> &results, bool show_all=false)
Definition: TheWarehouse.h:487
int prepare(std::vector< std::unique_ptr< Attribute >> conds)
prepares a query and returns an associated query_id (i.e. for use with the query function).
Definition: TheWarehouse.C:166
QueryCache clone() const
clone creates and returns an independent copy of the query in its current state.
Definition: TheWarehouse.h:293
constexpr bool is_sorted()
Check if the given index sequence is sorted ()internal function)
std::tuple< AttribType< Attribs >... > AttribTuple
Definition: TheWarehouse.h:213
std::unordered_map< std::vector< std::unique_ptr< Attribute > >, int > _query_cache
Definition: TheWarehouse.h:544
std::mutex _obj_mutex
Definition: TheWarehouse.h:549
virtual ~Attribute()
Definition: TheWarehouse.h:57
AttribSorted(TheWarehouse &w)
Definition: TheWarehouse.h:119
std::unordered_map< MooseObject *, std::size_t > _obj_ids
Definition: TheWarehouse.h:536
std::size_t operator()(const std::vector< std::unique_ptr< Attribute >> &attribs) const
Definition: TheWarehouse.h:167
void setKeysInner(K &k, Args &... args)
Definition: TheWarehouse.h:380
void update(MooseObject *obj)
update updates the metadata/attribute-info stored for the given object obj that must already exists i...
Definition: TheWarehouse.C:154
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse...
Definition: TheWarehouse.h:467
void setFrom(const Key &k)
Definition: TheWarehouse.h:117
unsigned int registerAttribute(const std::string &name, Args... dummy_args)
registers a new "tracked" attribute of type T for the warehouse.
Definition: TheWarehouse.h:430
std::vector< std::unique_ptr< Attribute > > attributes() const
attribs returns a copy of the constructed Attribute list for the query in its current state...
Definition: TheWarehouse.h:301
virtual void initFrom(const MooseObject *obj) override
initFrom reads and stores the desired meta-data from obj for later matching comparisons.
Definition: TheWarehouse.C:39
std::vector< T * > & queryInto(const std::vector< std::unique_ptr< Attribute >> &conds, std::vector< T *> &results)
queryInto takes the given conditions (i.e.
Definition: TheWarehouse.h:478
QueryCache & condition(Args &&... args)
Adds a new condition to the query.
Definition: TheWarehouse.h:285
typename T::Key KeyType
Definition: TheWarehouse.h:190
unsigned int attribID(const std::string &name)
Returns a unique ID associated with the given attribute name - i.e.
Definition: TheWarehouse.h:444
AttribSorted & operator=(const AttribSorted &)=default
std::vector< T * > & queryIntoUnsorted(std::vector< T *> &results, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Definition: TheWarehouse.h:325
AttribSorted(TheWarehouse &w, bool is_sorted)
Definition: TheWarehouse.h:120
virtual bool isMatch(const Attribute &other) const =0
isMatch returns true if the meta-data stored in this attribute is equivalent to that stored in other...
clonefunc(AttribSorted)
virtual void initFrom(const MooseObject *obj)=0
initFrom reads and stores the desired meta-data from obj for later matching comparisons.
std::vector< std::unique_ptr< Attribute > > _attrib_list
Definition: TheWarehouse.h:547
std::vector< std::vector< MooseObject * > > _obj_cache
Definition: TheWarehouse.h:540
virtual std::unique_ptr< Attribute > clone() const =0
clone creates and returns and identical (deep) copy of this attribute - i.e.