...
 
Commits (8)
......@@ -46,10 +46,4 @@
namespace OpenVolumeMesh {
BaseProperty& BaseProperty::operator=(const BaseProperty& _cpy) {
resMan_ = _cpy.resMan_;
lock_ = _cpy.lock_;
return *this;
}
} // Namespace OpenVolumeMesh
......@@ -55,11 +55,11 @@ class BaseProperty {
public:
friend class ResourceManager;
explicit BaseProperty(ResourceManager& _resMan) : resMan_(_resMan), lock_(false) {}
explicit BaseProperty(ResourceManager& _resMan) : resMan_(&_resMan) {}
BaseProperty(const BaseProperty& _cpy) : resMan_(_cpy.resMan_), lock_(_cpy.lock_) {}
explicit BaseProperty(const BaseProperty& _cpy) : resMan_(_cpy.resMan_) {}
BaseProperty& operator=(const BaseProperty& _cpy);
BaseProperty& operator=(const BaseProperty& _cpy) = delete;
virtual ~BaseProperty() {}
......@@ -87,6 +87,9 @@ public:
virtual const std::string typeNameWrapper() const = 0;
/// return the PropertyPtr shared_ptr use count
virtual long use_count() const = 0;
protected:
virtual void delete_multiple_entries(const std::vector<bool>& _tags) = 0;
......@@ -95,15 +98,9 @@ protected:
virtual void set_handle(const OpenVolumeMeshHandle& /*_handle*/) = 0;
void lock() { lock_ = true; }
void unlock() { lock_ = false; }
bool locked() const { return lock_; }
ResourceManager& resMan_;
void setResMan(ResourceManager *resMan) { resMan_ = resMan;}
bool lock_;
ResourceManager* resMan_;
};
} // Namespace OpenVolumeMesh
......
......@@ -105,6 +105,8 @@ public:
virtual bool anonymous() const { return ptr::shared_ptr<PropT>::get()->name().empty(); }
virtual long use_count() const { return ptr::shared_ptr<PropT>::use_count(); }
protected:
virtual void delete_multiple_entries(const std::vector<bool>& _tags);
......
......@@ -62,9 +62,8 @@ PropertyPtr<PropT,HandleT>::~PropertyPtr() {
* remove it, since the resource manager is the
* only one who stores the property.
*/
if(!locked() && !persistent() && ptr::shared_ptr<PropT>::use_count() == 2) {
resMan_.release_property(HandleT(handle().idx()));
unlock();
if(resMan_ && !persistent() && use_count() == 2) {
resMan_->release_property(HandleT(handle().idx()));
}
}
......
......@@ -47,7 +47,20 @@ namespace OpenVolumeMesh {
ResourceManager::ResourceManager() {
}
ResourceManager::ResourceManager(const ResourceManager &other) {
ResourceManager::ResourceManager(const ResourceManager &other)
{
*this = other;
}
ResourceManager::ResourceManager(ResourceManager &&other)
{
*this = std::move(other);
}
ResourceManager &ResourceManager::operator=(const ResourceManager &other)
{
if (this == &other) return *this;
auto cloneProps = [this](const Properties &src, Properties &dest) {
dest.reserve(src.size());
for (BaseProperty *bp: src) {
......@@ -61,6 +74,25 @@ ResourceManager::ResourceManager(const ResourceManager &other) {
cloneProps(other.halfface_props_, halfface_props_);
cloneProps(other.cell_props_, cell_props_);
cloneProps(other.mesh_props_, mesh_props_);
return *this;
}
ResourceManager &ResourceManager::operator=(ResourceManager &&other)
{
auto moveProps = [this](Properties &&src, Properties &dest) {
dest = std::move(src);
for (auto prop: dest) {
prop->setResMan(this);
}
};
moveProps(std::move(other.vertex_props_), vertex_props_);
moveProps(std::move(other.edge_props_), edge_props_);
moveProps(std::move(other.halfedge_props_), halfedge_props_);
moveProps(std::move(other.face_props_), face_props_);
moveProps(std::move(other.halfface_props_), halfface_props_);
moveProps(std::move(other.cell_props_), cell_props_);
moveProps(std::move(other.mesh_props_), mesh_props_);
return *this;
}
ResourceManager::~ResourceManager() {
......
......@@ -77,6 +77,11 @@ class ResourceManager {
public:
ResourceManager();
ResourceManager(const ResourceManager &other);
ResourceManager(ResourceManager &&other);
ResourceManager &operator=(const ResourceManager &other);
// warning: after a move there may still be properties pointing to the old resman ("other"),
// maybe we should track all props?
ResourceManager &operator=(ResourceManager &&other);
virtual ~ResourceManager();
template <class PropT, class HandleT> friend class PropertyPtr;
......@@ -341,6 +346,9 @@ private:
template<class StdVecT>
void clearVec(StdVecT& _vec);
template<class StdVecT>
void updatePropHandles(StdVecT& _vec);
Properties vertex_props_;
Properties edge_props_;
......
......@@ -170,13 +170,11 @@ void ResourceManager::set_persistentT(PropT& _prop, bool _flag) {
template<class StdVecT>
void ResourceManager::remove_property(StdVecT& _vec, size_t _idx) {
(*(_vec.begin() + _idx))->lock();
delete *(_vec.begin() + _idx);
auto prop_ptr = _vec[_idx];
prop_ptr->setResMan(nullptr);
delete prop_ptr;
_vec.erase(_vec.begin() + _idx);
size_t n = _vec.size();
for(size_t i = 0; i < n; ++i) {
_vec[i]->set_handle(OpenVolumeMeshHandle((int)i));
}
updatePropHandles(_vec);
}
template<class StdVecT>
......@@ -199,23 +197,27 @@ void ResourceManager::entity_deleted(StdVecT& _vec, const OpenVolumeMeshHandle&
template<class StdVecT>
void ResourceManager::clearVec(StdVecT& _vec) {
StdVecT newVec;
for(typename StdVecT::iterator it = _vec.begin();
it != _vec.end(); ++it) {
if(!(*it)->persistent()) {
#ifndef NDEBUG
std::cerr << "Keeping property \"" << (*it)->name()
<< "\" since it is still in use!" << std::endl;
#endif
(*it)->resize(0);
newVec.push_back(*it);
for (auto prop: _vec) {
if (prop->use_count() == 1) {
// No-one else holds a PropertyPtr to this object.
prop->setResMan(nullptr);
delete prop;
} else {
newVec.push_back(prop);
}
else
delete *it;
}
_vec = newVec;
updatePropHandles(_vec);
}
template<class StdVecT>
void ResourceManager::updatePropHandles(StdVecT &_vec)
{
size_t n = _vec.size();
for(size_t i = 0; i < n; ++i) {
_vec[i]->set_handle(OpenVolumeMeshHandle((int)i));
}
}
} // Namespace OpenVolumeMesh
......@@ -99,8 +99,8 @@ EdgeHandle TopologyKernel::add_edge(const VertexHandle& _fromVertex,
// If the conditions are not fulfilled, assert will fail (instead
// of returning an invalid handle)
assert(_fromVertex.is_valid() && (size_t)_fromVertex.idx() < n_vertices());
assert(_toVertex.is_valid() && (size_t)_toVertex.idx() < n_vertices());
assert(_fromVertex.is_valid() && (size_t)_fromVertex.idx() < n_vertices() && !is_deleted(_fromVertex));
assert(_toVertex.is_valid() && (size_t)_toVertex.idx() < n_vertices() && !is_deleted(_toVertex));
// Test if edge does not exist, yet
if(!_allowDuplicates) {
......@@ -164,7 +164,7 @@ FaceHandle TopologyKernel::add_face(const std::vector<HalfEdgeHandle>& _halfedge
// Assert that halfedges are valid
for(std::vector<HalfEdgeHandle>::const_iterator it = _halfedges.begin(),
end = _halfedges.end(); it != end; ++it)
assert(it->is_valid() && (size_t)it->idx() < edges_.size() * 2u);
assert(it->is_valid() && (size_t)it->idx() < edges_.size() * 2u && !is_deleted(*it));
#endif
// Perform topology check
......@@ -253,7 +253,7 @@ FaceHandle TopologyKernel::add_face(const std::vector<VertexHandle>& _vertices)
// Assert that all vertices have valid indices
for(std::vector<VertexHandle>::const_iterator it = _vertices.begin(),
end = _vertices.end(); it != end; ++it)
assert(it->is_valid() && (size_t)it->idx() < n_vertices());
assert(it->is_valid() && (size_t)it->idx() < n_vertices() && !is_deleted(*it));
#endif
// Add edge for each pair of vertices
......@@ -381,7 +381,7 @@ CellHandle TopologyKernel::add_cell(const std::vector<HalfFaceHandle>& _halfface
// Assert that halffaces have valid indices
for(std::vector<HalfFaceHandle>::const_iterator it = _halffaces.begin(),
end = _halffaces.end(); it != end; ++it)
assert(it->is_valid() && ((size_t)it->idx() < faces_.size() * 2u));
assert(it->is_valid() && ((size_t)it->idx() < faces_.size() * 2u) && !is_deleted(*it));
#endif
// Perform topology check
......@@ -483,6 +483,9 @@ CellHandle TopologyKernel::add_cell(const std::vector<HalfFaceHandle>& _halfface
/// Set the vertices of an edge
void TopologyKernel::set_edge(const EdgeHandle& _eh, const VertexHandle& _fromVertex, const VertexHandle& _toVertex) {
assert(_fromVertex.is_valid() && (size_t)_fromVertex.idx() < n_vertices() && !is_deleted(_fromVertex));
assert(_toVertex.is_valid() && (size_t)_toVertex.idx() < n_vertices() && !is_deleted(_toVertex));
Edge& e = edge(_eh);
// Update bottom-up entries
......@@ -591,6 +594,8 @@ void TopologyKernel::set_cell(const CellHandle& _ch, const std::vector<HalfFaceH
*/
VertexIter TopologyKernel::delete_vertex(const VertexHandle& _h) {
assert(!is_deleted(_h));
std::vector<VertexHandle> vs;
vs.push_back(_h);
......@@ -641,6 +646,8 @@ VertexIter TopologyKernel::delete_vertex(const VertexHandle& _h) {
*/
EdgeIter TopologyKernel::delete_edge(const EdgeHandle& _h) {
assert(!is_deleted(_h));
std::vector<EdgeHandle> es;
es.push_back(_h);
......@@ -682,6 +689,8 @@ EdgeIter TopologyKernel::delete_edge(const EdgeHandle& _h) {
*/
FaceIter TopologyKernel::delete_face(const FaceHandle& _h) {
assert(!is_deleted(_h));
std::vector<FaceHandle> fs;
fs.push_back(_h);
......@@ -711,6 +720,7 @@ FaceIter TopologyKernel::delete_face(const FaceHandle& _h) {
*/
CellIter TopologyKernel::delete_cell(const CellHandle& _h) {
assert(!is_deleted(_h));
return delete_cell_core(_h);
}
......
......@@ -126,7 +126,9 @@ bool FileManager::getCleanLine(std::istream& _ifs, std::string& _string, bool _s
}
if(_ifs.eof()) {
std::cerr << "End of file reached while searching for input!" << std::endl;
if (verbosity_level_ >= 2) {
std::cerr << "End of file reached while searching for input!" << std::endl;
}
return false;
}
}
......@@ -141,7 +143,9 @@ bool FileManager::isHexahedralMesh(const std::string& _filename) const {
std::ifstream iff(_filename.c_str(), std::ios::in);
if(!iff.good()) {
std::cerr << "Could not open file " << _filename << " for reading!" << std::endl;
if (verbosity_level_ >= 1) {
std::cerr << "Could not open file " << _filename << " for reading!" << std::endl;
}
iff.close();
return false;
}
......@@ -185,7 +189,9 @@ bool FileManager::isTetrahedralMesh(const std::string& _filename) const {
std::ifstream iff(_filename.c_str(), std::ios::in);
if(!iff.good()) {
std::cerr << "Could not open file " << _filename << " for reading!" << std::endl;
if (verbosity_level_ >= 1) {
std::cerr << "Could not open file " << _filename << " for reading!" << std::endl;
}
iff.close();
return false;
}
......
......@@ -45,6 +45,8 @@
#include <string>
#include <fstream>
#include <istream>
#include <ostream>
namespace OpenVolumeMesh {
......@@ -66,6 +68,34 @@ public:
/// Default destructor
~FileManager();
/**
* \brief set minimum level for errors that are printed to std::cerr
* @param _level 0: no output; 1: only errors; 2: warnings/info
*/
void setVerbosityLevel(int _level) { verbosity_level_ = _level;}
/**
* \brief Read a mesh from an std::istream
*
* Returns true if the file was successfully read. The mesh
* is stored in parameter _mesh. If something goes wrong,
* this function returns false.
*
* @param _istream The stream to read the mesh from
* @param _mesh A reference to an OpenVolumeMesh instance
* @param _topologyCheck Pass true if you want to perform a topology check
* each time an entity is added (slower performance)
* @param _computeBottomUpIncidences Pass true if you want the file manager
* to directly compute the bottom-up incidences
* for the mesh. (Note: These are needed for
* some iterators to work, see documentation)
*/
template <class MeshT>
bool readStream(std::istream &_istream, MeshT& _mesh,
bool _topologyCheck = true,
bool _computeBottomUpIncidences = true) const;
/**
* \brief Read a mesh from a file
*
......@@ -87,6 +117,16 @@ public:
bool _topologyCheck = true,
bool _computeBottomUpIncidences = true) const;
/**
* \brief Write a mesh to an std::ostream
*
* @param _ostream The stream to write the mesh to
* @param _mesh A const reference to an OpenVolumeMesh instance
*/
template <class MeshT>
void writeStream(std::ostream &_ostream, const MeshT& _mesh) const;
/**
* \brief Write a mesh to a file
*
......@@ -134,6 +174,9 @@ private:
// Get a whole line from file
bool getCleanLine(std::istream& ifs, std::string& _string, bool _skipEmptyLines = true) const;
int verbosity_level_ = 3;
};
} // Namespace IO
......