vsg  1.1.0
VulkanSceneGraph library
SharedObjects.h
1 #pragma once
2 
3 /* <editor-fold desc="MIT License">
4 
5 Copyright(c) 2022 Robert Osfield
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 
9 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 
13 </editor-fold> */
14 
15 #include <vsg/core/Inherit.h>
16 #include <vsg/core/compare.h>
17 #include <vsg/io/stream.h>
18 
19 #include <map>
20 #include <mutex>
21 #include <ostream>
22 #include <set>
23 
24 namespace vsg
25 {
26 
27  // forward declare
28  class SuitableForSharing;
29 
31  class VSG_DECLSPEC SharedObjects : public Inherit<Object, SharedObjects>
32  {
33  public:
34  SharedObjects();
35 
36  template<class T>
37  ref_ptr<T> shared_default();
38 
39  template<class T>
40  void share(ref_ptr<T>& object);
41 
42  template<class T, typename Func>
43  void share(ref_ptr<T>& object, Func init);
44 
45  template<class C>
46  void share(C& container);
47 
50 
52  std::set<Path> excludedExtensions;
53 
55  virtual bool suitable(const Path& filename) const;
56 
58  virtual bool contains(const Path& filename, ref_ptr<const Options> options = {}) const;
59 
61  virtual void add(ref_ptr<Object> object, const Path& filename, ref_ptr<const Options> options = {});
62 
64  virtual bool remove(const Path& filename, ref_ptr<const Options> options = {});
65 
67  void clear();
68 
69  // clear all the singularly referenced objects
70  void prune();
71 
73  void report(std::ostream& out);
74 
75  protected:
76  virtual ~SharedObjects();
77 
78  mutable std::recursive_mutex _mutex;
79  std::map<std::type_index, ref_ptr<Object>> _defaults;
80  std::map<std::type_index, std::set<ref_ptr<Object>, DereferenceLess>> _sharedObjects;
81  };
82  VSG_type_name(vsg::SharedObjects);
83 
85  class VSG_DECLSPEC LoadedObject : public Inherit<Object, LoadedObject>
86  {
87  public:
88  Path filename;
89  ref_ptr<Options> options;
90  ref_ptr<Object> object;
91 
92  LoadedObject(const Path& in_filename, ref_ptr<const Options> in_options, ref_ptr<Object> in_object = {});
93 
94  void traverse(Visitor& visitor) override;
95  void traverse(ConstVisitor& visitor) const override;
96 
97  int compare(const Object& rhs_object) const override;
98  };
99  VSG_type_name(vsg::LoadedObject);
100 
108  class VSG_DECLSPEC SuitableForSharing : public Inherit<ConstVisitor, SuitableForSharing>
109  {
110  public:
111  bool suitableForSharing = true;
112 
113  void apply(const Object& object) override;
114  void apply(const PagedLOD& plod) override;
115 
116  bool suitable(const Object* object)
117  {
118  suitableForSharing = true;
119  if (object) object->accept(*this);
120  return suitableForSharing;
121  }
122  };
123  VSG_type_name(vsg::SuitableForSharing);
124 
125  // implementation of template method
126  template<class T>
127  ref_ptr<T> SharedObjects::shared_default()
128  {
129  std::scoped_lock<std::recursive_mutex> lock(_mutex);
130 
131  auto id = std::type_index(typeid(T));
132  auto& def = _defaults[id];
133  auto def_T = def.cast<T>(); // should be able to do a static cast
134  if (!def_T)
135  {
136  def_T = T::create();
137  auto& shared_objects = _sharedObjects[id];
138  if (auto itr = shared_objects.find(def_T); itr != shared_objects.end())
139  {
140  def_T = (static_cast<T*>(itr->get()));
141  }
142  else
143  {
144  shared_objects.insert(def_T);
145  }
146 
147  def = def_T;
148  }
149 
150  return def_T;
151  }
152 
153  // implementation of template method
154  template<class T>
155  void SharedObjects::share(ref_ptr<T>& object)
156  {
157  std::scoped_lock<std::recursive_mutex> lock(_mutex);
158 
159  if (suitableForSharing && !suitableForSharing->suitable(object.get())) return;
160 
161  auto id = std::type_index(typeid(T));
162  auto& shared_objects = _sharedObjects[id];
163  if (auto itr = shared_objects.find(object); itr != shared_objects.end())
164  {
165  object = ref_ptr<T>(static_cast<T*>(itr->get()));
166  return;
167  }
168 
169  shared_objects.insert(object);
170  }
171 
172  // implementation of template method
173  template<class T, typename Func>
174  void SharedObjects::share(ref_ptr<T>& object, Func init)
175  {
176  {
177  std::scoped_lock<std::recursive_mutex> lock(_mutex);
178 
179  auto id = std::type_index(typeid(T));
180  auto& shared_objects = _sharedObjects[id];
181  if (auto itr = shared_objects.find(object); itr != shared_objects.end())
182  {
183  object = ref_ptr<T>(static_cast<T*>(itr->get()));
184  return;
185  }
186  }
187 
188  init(object);
189 
190  {
191  std::scoped_lock<std::recursive_mutex> lock(_mutex);
192  auto id = std::type_index(typeid(T));
193  auto& shared_objects = _sharedObjects[id];
194  if (suitableForSharing && suitableForSharing->suitable(object.get()))
195  {
196  shared_objects.insert(object);
197  }
198  }
199  }
200 
201  // implementation of template method
202  template<class C>
203  void SharedObjects::share(C& container)
204  {
205  for (auto& object : container)
206  {
207  share(object);
208  }
209  }
210 
211 } // namespace vsg
Definition: ConstVisitor.h:147
Definition: Inherit.h:28
Helper class for sharing of objects loaded from files.
Definition: SharedObjects.h:86
int compare(const Object &rhs_object) const override
compare two objects, return -1 if this object is less than rhs, return 0 if it's equal,...
Definition: Object.h:42
Definition: PagedLOD.h:36
Definition: Path.h:32
class for facilitating the sharing of instances of objects that have the same properties.
Definition: SharedObjects.h:32
void report(std::ostream &out)
write out stats of objects held, types of objects and their reference counts
std::set< Path > excludedExtensions
set of lower case file extensions for file types that should not be included in this SharedObjects
Definition: SharedObjects.h:52
virtual bool remove(const Path &filename, ref_ptr< const Options > options={})
remove entry associated with filename.
virtual bool suitable(const Path &filename) const
return true if the filename is of a type suitable for inclusion in this SharedObjects
void clear()
clear all the internal structures leaving no Objects cached.
ref_ptr< SuitableForSharing > suitableForSharing
visitor that checks a loaded object and its children for suitability for sharing in SharedObjects
Definition: SharedObjects.h:49
virtual bool contains(const Path &filename, ref_ptr< const Options > options={}) const
check for an entry associated with filename.
virtual void add(ref_ptr< Object > object, const Path &filename, ref_ptr< const Options > options={})
add entry that matches filename and options.
Definition: SharedObjects.h:109
Definition: Visitor.h:147
Definition: ref_ptr.h:22
less functor for comparing ref_ptr<Object> typically used with std::set<> etc.
Definition: compare.h:107