SMTK  @SMTK_VERSION@
Simulation Modeling Tool Kit
Cache.h
1 //=========================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //=========================================================================
10 #ifndef smtk_geometry_Cache_h
11 #define smtk_geometry_Cache_h
12 
13 #include "smtk/geometry/GeometryForBackend.h"
14 #include "smtk/geometry/Resource.h"
15 
16 #include <map>
17 
18 namespace smtk
19 {
20 namespace geometry
21 {
22 
37 template<typename BaseClass>
38 class Cache : public BaseClass
39 {
40 public:
41  smtkTypeMacro(Cache);
42  smtkSharedFromThisMacro(Geometry);
43  smtkSuperclassMacro(BaseClass);
44 
45  using GenerationNumber = Geometry::GenerationNumber;
46  using DataType = typename BaseClass::DataType;
47  using BoundingBox = Geometry::BoundingBox;
48  using Visitor = Geometry::Visitor;
49  static constexpr GenerationNumber Invalid = Geometry::Invalid;
50  static constexpr GenerationNumber Initial = Geometry::Initial;
51 
53  struct CacheEntry
54  {
55  GenerationNumber m_generation;
56  DataType m_geometry;
57 
58  CacheEntry()
59  : m_generation(Invalid)
60  {
61  }
62 
63  CacheEntry(CacheEntry&&) noexcept = default;
64  CacheEntry(const CacheEntry&) = default;
65  CacheEntry(GenerationNumber gen, const DataType& data)
66  : m_generation(gen)
67  , m_geometry(data)
68  {
69  }
70  CacheEntry& operator=(const CacheEntry&) = default;
71 
72  bool isValid() const { return m_generation != Invalid; }
73  };
74 
99  virtual void queryGeometry(const smtk::resource::PersistentObject::Ptr&, CacheEntry& cache) const
100  {
101  cache.m_generation = Invalid;
102  }
103 
107  GenerationNumber generationNumber(const smtk::resource::PersistentObject::Ptr& obj) const override
108  {
109  if (obj)
110  {
111  auto it = m_cache.find(obj->id());
112  bool found = it != m_cache.end();
113  if (found && it->second.m_geometry)
114  { // Cache is clean.
115  return it->second.m_generation;
116  }
117  else if (found)
118  { // Cache was marked dirty.
119  this->queryGeometry(obj, it->second);
120  if (!it->second.isValid())
121  {
122  m_cache.erase(it);
123  }
124  else
125  {
126  return it->second.m_generation;
127  }
128  }
129  else
130  { // No cache entry yet; try to add one.
131  CacheEntry entry;
132  this->queryGeometry(obj, entry);
133  if (entry.isValid())
134  {
135  m_cache[obj->id()] = entry;
136  return entry.m_generation;
137  }
138  }
139  }
140  return Invalid;
141  }
142 
144  void bounds(const smtk::resource::PersistentObject::Ptr& obj, BoundingBox& bds) const override
145  {
146  if (obj)
147  {
148  auto it = m_cache.find(obj->id());
149  bool found = it != m_cache.end();
150  if (found && it->second.m_geometry)
151  { // Cache is clean:
152  this->geometricBounds(it->second.m_geometry, bds);
153  return;
154  }
155  else if (found)
156  { // Cache was marked dirty. Update it:
157  this->queryGeometry(obj, it->second);
158  if (it->second.isValid())
159  {
160  this->geometricBounds(it->second.m_geometry, bds);
161  return;
162  }
163  else
164  {
165  m_cache.erase(it);
166  }
167  }
168  else
169  {
170  CacheEntry entry;
171  this->queryGeometry(obj, entry);
172  if (entry.isValid())
173  {
174  m_cache[obj->id()] = entry;
175  this->geometricBounds(entry.m_geometry, bds);
176  return;
177  }
178  }
179  }
180  // Object is invalid or has no geometry; return invalid bounds.
181  bds[0] = bds[2] = bds[4] = 0.0;
182  bds[1] = bds[3] = bds[5] = -1.0;
183  }
184 
186  DataType& data(const smtk::resource::PersistentObject::Ptr& obj) const override
187  {
188  if (obj)
189  {
190  auto it = m_cache.find(obj->id());
191  bool found = it != m_cache.end();
192  if (found && it->second.m_geometry)
193  { // Cache is clean.
194  return it->second.m_geometry;
195  }
196  else if (found)
197  { // Cache was marked dirty. Update it:
198  this->queryGeometry(obj, it->second);
199  if (it->second.isValid())
200  {
201  return it->second.m_geometry;
202  }
203  else
204  {
205  m_cache.erase(it);
206  }
207  }
208  else
209  { // No cache existed. See if we can create an entry:
210  CacheEntry entry;
211  this->queryGeometry(obj, entry);
212  if (entry.isValid())
213  {
214  m_cache[obj->id()] = entry;
215  return m_cache[obj->id()].m_geometry;
216  }
217  }
218  }
219  static DataType invalid;
220  return invalid;
221  }
222 
235  void visit(Visitor visitor) const override
236  {
237  this->update();
238  auto rsrc = this->resource();
239  if (rsrc)
240  {
241  auto it = m_cache.begin();
242  for (auto entry = it; entry != m_cache.end(); entry = it)
243  {
244  ++it;
245  auto comp = rsrc->find(entry->first);
246  if (comp)
247  {
248  visitor(comp, entry->second.m_generation);
249  }
250  else if (entry->first == rsrc->id())
251  {
252  visitor(rsrc, entry->second.m_generation);
253  }
254  // else remove cache entry?
255  }
256  }
257  }
258 
264  void markModified(const smtk::resource::PersistentObject::Ptr& obj) override
265  {
266  if (obj)
267  {
268  ++this->BaseClass::m_lastModified;
269  auto it = m_cache.find(obj->id());
270  if (it != m_cache.end())
271  {
272  DataType blank; // Assume default constructor creates "null" data.
273  it->second.m_geometry = blank;
274  }
275  else
276  {
277  CacheEntry invalid;
278  m_cache[obj->id()] = invalid;
279  }
280  }
281  }
282 
290  bool erase(const smtk::common::UUID& uid) override { return m_cache.erase(uid) > 0; }
291 
292 protected:
293  mutable std::map<smtk::common::UUID, CacheEntry> m_cache;
294 };
295 
296 } // namespace geometry
297 } // namespace smtk
298 
299 #endif // smtk_geometry_Cache_h
smtk
The main namespace for the Simulation Modeling Tool Kit (SMTK).
Definition: doc.h:33
smtk::geometry::Cache::CacheEntry::m_generation
GenerationNumber m_generation
A generation number or Invalid.
Definition: Cache.h:55
smtk::geometry::Cache::bounds
void bounds(const smtk::resource::PersistentObject::Ptr &obj, BoundingBox &bds) const override
Return the geometric bounds.
Definition: Cache.h:144
smtk::geometry::Geometry::Invalid
static constexpr GenerationNumber Invalid
A special generation number that marks an object as having no geometric representation.
Definition: Geometry.h:71
smtk::geometry::Cache::generationNumber
GenerationNumber generationNumber(const smtk::resource::PersistentObject::Ptr &obj) const override
Return the generation number of geometry held by the cache for the given object.
Definition: Cache.h:107
smtk::geometry::Cache::markModified
void markModified(const smtk::resource::PersistentObject::Ptr &obj) override
Remove a cache entry's geometry (but keep its generation number intact).
Definition: Cache.h:264
smtk::common::UUID
Definition: UUID.h:38
smtk::geometry::Geometry::Visitor
std::function< bool(const resource::PersistentObject::Ptr &, GenerationNumber)> Visitor
The signature of functions used to visit all objects with tessellation data.
Definition: Geometry.h:81
smtk::geometry::Cache::erase
bool erase(const smtk::common::UUID &uid) override
Remove a cache entry completely.
Definition: Cache.h:290
smtk::geometry::Geometry::Initial
static constexpr GenerationNumber Initial
The lowest valid generation number (which may be used as the initial value).
Definition: Geometry.h:74
smtk::geometry::Geometry::BoundingBox
std::array< double, 6 > BoundingBox
A bounding box is represented as an array of 6 numbers, ordered xmin, xmax, ymin, ymax,...
Definition: Geometry.h:78
smtk::geometry::Cache::CacheEntry::m_geometry
DataType m_geometry
Geometry held by the cache.
Definition: Cache.h:56
smtk::geometry::Cache
A geometry provider that uses a cache to answer queries.
Definition: Cache.h:38
smtk::geometry::Geometry
A base class for objects which can provide renderable geometry.
Definition: Geometry.h:60
smtk::geometry::Cache::queryGeometry
virtual void queryGeometry(const smtk::resource::PersistentObject::Ptr &, CacheEntry &cache) const
Create a geometric representation of an object on demand.
Definition: Cache.h:99
smtk::geometry::Cache::CacheEntry
The values held by the geometry cache.
Definition: Cache.h:53
smtk::geometry::Geometry::GenerationNumber
size_t GenerationNumber
An integral type to hold monotonically increasing generation numbers (a.k.a.
Definition: Geometry.h:68
smtk::geometry::Cache::data
DataType & data(const smtk::resource::PersistentObject::Ptr &obj) const override
Provide access to the actual cached geometry reference.
Definition: Cache.h:186
smtk::geometry::Cache::visit
void visit(Visitor visitor) const override
Visit each persistent object that has renderable geometry.
Definition: Cache.h:235