Developer Documentation
Loading...
Searching...
No Matches
ResourceManagerT_impl.hh
1#pragma once
2/*===========================================================================*\
3 * *
4 * OpenVolumeMesh *
5 * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
6 * www.openvolumemesh.org *
7 * *
8 *---------------------------------------------------------------------------*
9 * This file is part of OpenVolumeMesh. *
10 * *
11 * OpenVolumeMesh is free software: you can redistribute it and/or modify *
12 * it under the terms of the GNU Lesser General Public License as *
13 * published by the Free Software Foundation, either version 3 of *
14 * the License, or (at your option) any later version with the *
15 * following exceptions: *
16 * *
17 * If other files instantiate templates or use macros *
18 * or inline functions from this file, or you compile this file and *
19 * link it with other files to produce an executable, this file does *
20 * not by itself cause the resulting executable to be covered by the *
21 * GNU Lesser General Public License. This exception does not however *
22 * invalidate any other reasons why the executable file might be *
23 * covered by the GNU Lesser General Public License. *
24 * *
25 * OpenVolumeMesh is distributed in the hope that it will be useful, *
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
28 * GNU Lesser General Public License for more details. *
29 * *
30 * You should have received a copy of the GNU LesserGeneral Public *
31 * License along with OpenVolumeMesh. If not, *
32 * see <http://www.gnu.org/licenses/>. *
33 * *
34\*===========================================================================*/
35
36#include <OpenVolumeMesh/Core/ResourceManager.hh>
37#include <OpenVolumeMesh/Core/Properties/PropertyPtr.hh>
38#include <OpenVolumeMesh/Core/detail/internal_type_name.hh>
39
40namespace OpenVolumeMesh {
41
42
43template<typename EntityTag>
44detail::Tracker<PropertyStorageBase> &
45ResourceManager::storage_tracker() const
46{
47 return storage_trackers_.get<EntityTag>();
48}
49
50
51// Change all properties to be private, such that they are
52// not visible anymore from the mesh API.
53// Crucially, this does not delete props that are in use,
54// i.e., they are kept in storage_tracker for index updates.
55template<typename EntityTag>
57{
58 for (auto prop: persistent_props_.get<EntityTag>()) {
59 prop->set_persistent(false);
60 }
61 persistent_props_.get<EntityTag>().clear();
62
63 for (auto prop: storage_tracker<EntityTag>()) {
64 prop->set_shared(false);
65 }
66}
67
68template <typename Handle>
69void ResourceManager::swap_property_elements(Handle _idx_a, Handle _idx_b)
70{
71 static_assert(is_handle_v<Handle>);
72 for (auto &prop: storage_tracker<typename Handle::EntityTag>()) {
73 prop->swap(_idx_a.uidx(), _idx_b.uidx());
74 }
75}
76
77template <typename Handle>
78void ResourceManager::copy_property_elements(Handle _idx_a, Handle _idx_b)
79{
80 static_assert(is_handle_v<Handle>);
81 for (auto &prop: storage_tracker<typename Handle::EntityTag>()) {
82 prop->copy(_idx_a.uidx(), _idx_b.uidx());
83 }
84}
85
86template<class T>
87VertexPropertyT<T> ResourceManager::request_vertex_property(const std::string& _name, const T _def) {
88
89 return request_property<T, Entity::Vertex>(_name, _def);
90}
91
92template<class T>
93EdgePropertyT<T> ResourceManager::request_edge_property(const std::string& _name, const T _def) {
94
95 return request_property<T, Entity::Edge>(_name, _def);
96}
97
98template<class T>
99HalfEdgePropertyT<T> ResourceManager::request_halfedge_property(const std::string& _name, const T _def) {
100
101 return request_property<T, Entity::HalfEdge>(_name, _def);
102}
103
104template<class T>
105FacePropertyT<T> ResourceManager::request_face_property(const std::string& _name, const T _def) {
106
107 return request_property<T, Entity::Face>(_name, _def);
108}
109
110template<class T>
111HalfFacePropertyT<T> ResourceManager::request_halfface_property(const std::string& _name, const T _def) {
112 return request_property<T, Entity::HalfFace>(_name, _def);
113}
114
115template<class T>
116CellPropertyT<T> ResourceManager::request_cell_property(const std::string& _name, const T _def) {
117
118 return request_property<T, Entity::Cell>(_name, _def);
119}
120
121template<class T>
122MeshPropertyT<T> ResourceManager::request_mesh_property(const std::string& _name, const T _def) {
123
124 return request_property<T, Entity::Mesh>(_name, _def);
125}
126
127template<typename T, typename EntityTag>
128std::optional<PropertyPtr<T, EntityTag>>
129ResourceManager::internal_find_property(const std::string& _name) const
130{
131 if(_name.empty()) {
132 return {};
133 }
134
135 auto type_name = detail::internal_type_name<T>();
136
137 for(auto &prop: storage_tracker<EntityTag>())
138 {
139 if(prop->shared()
140 && prop->name() == _name
141 && prop->internal_type_name() == type_name)
142 {
143 return prop_ptr_from_storage<T, EntityTag>(prop);
144 }
145 }
146 return {};
147}
148
149template<class T, class EntityTag>
150PropertyPtr<T, EntityTag> ResourceManager::internal_create_property(
151 std::string _name, const T _def, bool _shared) const
152{
153 auto storage = std::make_shared<PropertyStorageT<T>>(
154 &storage_tracker<EntityTag>(),
155 std::move(_name),
156 EntityTag::type(),
157 std::move(_def),
158 _shared);
159 storage->resize(n<EntityTag>());
160 return PropertyPtr<T, EntityTag>(std::move(storage));
161}
162
163template<typename T, typename EntityTag>
165{
166 auto prop = internal_find_property<T, EntityTag>(_name);
167 if (prop)
168 return *prop;
169 bool shared = !_name.empty();
170 return internal_create_property<T, EntityTag>(_name, _def, shared);
171}
172
173template<typename T, typename EntityTag>
174std::optional<PropertyPtr<T, EntityTag>>
175ResourceManager::create_persistent_property(std::string _name, const T _def)
176{
177 auto prop = internal_find_property<T, EntityTag>(_name);
178 if (prop)
179 return {};
180 auto ptr = internal_create_property<T, EntityTag>(std::move(_name), _def, true);
181 set_persistent(ptr);
182 return ptr;
183}
184
185template<typename T, typename EntityTag>
186std::optional<PropertyPtr<T, EntityTag>>
187ResourceManager::create_shared_property(std::string _name, const T _def)
188{
189 auto prop = internal_find_property<T, EntityTag>(_name);
190 if (prop)
191 return {};
192 return internal_create_property<T, EntityTag>(std::move(_name), _def, true);
193}
194template<typename T, typename EntityTag>
196ResourceManager::create_private_property(std::string _name, const T _def) const
197{
198 return internal_create_property<T, EntityTag>(std::move(_name), _def, false);
199}
200
201template<typename T, typename EntityTag>
202std::optional<PropertyPtr<T, EntityTag>>
203ResourceManager::get_property(const std::string& _name)
204{
205 return internal_find_property<T, EntityTag>(_name);
206}
207
208template<typename T, typename EntityTag>
209std::optional<const PropertyPtr<T, EntityTag>>
210ResourceManager::get_property(const std::string& _name) const
211{
212 return internal_find_property<T, EntityTag>(_name);
213}
214
215
216template<typename T, class EntityTag>
217void ResourceManager::set_shared(PropertyPtr<T, EntityTag>& _prop, bool _enable)
218{
219 if(_enable == _prop.shared()) return;
220
221 auto sptr = std::static_pointer_cast<PropertyStorageBase>(_prop.storage());
222 if (_enable) {
223 if (_prop.anonymous()) {
224 throw std::runtime_error("Shared properties must have a name!");
225 }
226 auto existing = internal_find_property<T, EntityTag>(_prop.name());
227 if (existing) {
228 throw std::runtime_error("A shared property with this name, type and entity type already exists.");
229 }
230 } else {
231 set_persistent(_prop, false);
232 }
233 sptr->set_shared(_enable);
234}
235
236template<typename T, class EntityTag>
237void ResourceManager::set_persistent(PropertyPtr<T, EntityTag>& _prop, bool _enable)
238{
239 if(_enable == _prop.persistent()) return;
240
241 auto sptr = std::static_pointer_cast<PropertyStorageBase>(_prop.storage());
242 if (_enable) {
243 if (!_prop.shared()) {
244 throw std::runtime_error("Persistent properties must be shared (set_shared).");
245 }
246 persistent_props_.get<EntityTag>().insert(sptr);
247 } else {
248 persistent_props_.get<EntityTag>().erase(sptr);
249 }
250 sptr->set_persistent(_enable);
251}
252
253
254template<class EntityTag>
255void ResourceManager::resize_props(size_t _n)
256{
257 static_assert(is_entity_v<EntityTag>);
258 for (auto &prop: storage_tracker<EntityTag>()) {
259 prop->resize(_n);
260 }
261}
262
263template<class EntityTag>
264void ResourceManager::reserve_props(size_t _n)
265{
266 static_assert(is_entity_v<EntityTag>);
267 for (auto &prop: storage_tracker<EntityTag>()) {
268 prop->reserve(_n);
269 }
270}
271
272
273template<typename Handle>
274void ResourceManager::entity_deleted(Handle _h)
275{
276 static_assert(is_handle_v<Handle>);
277 for (auto &prop: storage_tracker<typename Handle::EntityTag>()) {
278 prop->delete_element(_h.uidx());
279 }
280}
281
282
283template<typename EntityTag>
285 return storage_tracker<EntityTag>().size();
286}
287
288template<typename EntityTag>
290 return persistent_props_.get<EntityTag>().size();
291}
292
293
294#if 0
295template<typename EntityTag>
296void ResourceManager::assignPropertiesFrom(ResourceManager const& _src)
297{
298 auto &src_all = _src.template storage_tracker<EntityTag>();
299 auto &dst_all = storage_tracker<EntityTag>();
300
301 // If possible, re-use existing properties instead of copying
302 // everything blindly.
303
304 auto &persistent = persistent_props_.get<EntityTag>();
305
306 // TODO OPT: this will be slow for many props (quadratic) - we could do this in nlogn.
307 // sort both sets by key (name, type), then traverse in parallel
308 for (const auto &srcprop: src_all) {
309 bool found = false;
310 if (!srcprop->shared()) {
311 // it does not make sense to copy private props,
312 // noone could access them
313 return;
314 }
315 // try to find and update existing properties in dst
316 for (auto it = dst_all.begin(); it != dst_all.end(); ++it)
317 {
318 auto &dstprop = *it;
319 if (!dstprop->shared()) {
320 return;
321 }
322 if (dstprop->name() == srcprop->name()
323 && dstprop->internal_type_name() == srcprop->internal_type_name())
324 {
325 // found a correspondence!
326 dstprop->assign_values_from(srcprop);
327 if (srcprop->persistent() && !dstprop->persistent()) {
328 persistent.insert(dstprop->shared_from_this());
329 }
330 found = true;
331 break;
332 }
333 }
334
335 if (!found)
336 {
337 auto dstprop = srcprop->clone();
338 dstprop->set_tracker(&storage_tracker<EntityTag>());
339 if (srcprop->persistent()) {
340 persistent.insert(dstprop->shared_from_this());
341 }
342 }
343 }
344}
345#endif
346
347
348
349// We define this here to avoid circular dependencies:
350
351template <class T, typename Entity>
352PropertyPtr<T, Entity>::PropertyPtr(ResourceManager *mesh, std::string _name, T const &_def)
353{
354 *this = mesh->request_property<T, Entity>(_name, _def);
355}
356
357
358template <class T, typename EntityTag>
359PropertyPtr<T, EntityTag> ResourceManager::
360prop_ptr_from_storage(PropertyStorageBase *_prop)
361{
362 auto ps = std::static_pointer_cast<PropertyStorageT<T>>(
363 _prop->shared_from_this());
364 return PropertyPtr<T, EntityTag>(std::move(ps));
365}
366
367
368
369} // Namespace OpenVolumeMesh
std::optional< PropertyPtr< T, EntityTag > > create_shared_property(std::string _name, const T _def=T())
std::optional< PropertyPtr< T, EntityTag > > get_property(const std::string &_name)
void clear_props()
drop persistent properties.
size_t n_persistent_props() const
number of persistent properties
std::optional< PropertyPtr< T, EntityTag > > create_persistent_property(std::string _name, const T _def=T())
size_t n_props() const
number of tracked properties
PropertyPtr< T, EntityTag > create_private_property(std::string _name={}, const T _def=T()) const
PropertyPtr< T, EntityTag > request_property(const std::string &_name=std::string(), const T _def=T())