mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 13:43:40 +00:00
Wait for threads in iterator destructor
This commit is contained in:
+101
-86
@@ -1,58 +1,58 @@
|
|||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* *
|
* *
|
||||||
* This file is part of IfcOpenShell. *
|
* This file is part of IfcOpenShell. *
|
||||||
* *
|
* *
|
||||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the Lesser GNU General Public License as published by *
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (at your option) any later version. *
|
||||||
* *
|
* *
|
||||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
* Lesser GNU General Public License for more details. *
|
* Lesser GNU General Public License for more details. *
|
||||||
* *
|
* *
|
||||||
* You should have received a copy of the Lesser GNU General Public License *
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* *
|
* *
|
||||||
* Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) *
|
* Geometrical data in an IFC file consists of shapes (IfcShapeRepresentation) *
|
||||||
* and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). *
|
* and instances (SUBTYPE OF IfcBuildingElement e.g. IfcWindow). *
|
||||||
* *
|
* *
|
||||||
* IfcGeom::Representation::Triangulation is a class that represents a *
|
* IfcGeom::Representation::Triangulation is a class that represents a *
|
||||||
* triangulated IfcShapeRepresentation. *
|
* triangulated IfcShapeRepresentation. *
|
||||||
* Triangulation.verts is a 1 dimensional vector of float defining the *
|
* Triangulation.verts is a 1 dimensional vector of float defining the *
|
||||||
* cartesian coordinates of the vertices of the triangulated shape in the *
|
* cartesian coordinates of the vertices of the triangulated shape in the *
|
||||||
* format of [x1,y1,z1,..,xn,yn,zn] *
|
* format of [x1,y1,z1,..,xn,yn,zn] *
|
||||||
* Triangulation.faces is a 1 dimensional vector of int containing the *
|
* Triangulation.faces is a 1 dimensional vector of int containing the *
|
||||||
* indices of the triangles referencing positions in Triangulation.verts *
|
* indices of the triangles referencing positions in Triangulation.verts *
|
||||||
* Triangulation.edges is a 1 dimensional vector of int in {0,1} that dictates*
|
* Triangulation.edges is a 1 dimensional vector of int in {0,1} that dictates*
|
||||||
* the visibility of the edges that span the faces in Triangulation.faces *
|
* the visibility of the edges that span the faces in Triangulation.faces *
|
||||||
* *
|
* *
|
||||||
* IfcGeom::Element represents the actual IfcBuildingElements. *
|
* IfcGeom::Element represents the actual IfcBuildingElements. *
|
||||||
* IfcGeomObject.name is the GUID of the element *
|
* IfcGeomObject.name is the GUID of the element *
|
||||||
* IfcGeomObject.type is the datatype of the element e.g. IfcWindow *
|
* IfcGeomObject.type is the datatype of the element e.g. IfcWindow *
|
||||||
* IfcGeomObject.mesh is a pointer to an IfcMesh *
|
* IfcGeomObject.mesh is a pointer to an IfcMesh *
|
||||||
* IfcGeomObject.transformation.matrix is a 4x3 matrix that defines the *
|
* IfcGeomObject.transformation.matrix is a 4x3 matrix that defines the *
|
||||||
* orientation and translation of the mesh in relation to the world origin *
|
* orientation and translation of the mesh in relation to the world origin *
|
||||||
* *
|
* *
|
||||||
* IfcGeom::Iterator::initialize() *
|
* IfcGeom::Iterator::initialize() *
|
||||||
* finds the most suitable representation contexts. Returns true iff *
|
* finds the most suitable representation contexts. Returns true iff *
|
||||||
* at least a single representation will process successfully *
|
* at least a single representation will process successfully *
|
||||||
* *
|
* *
|
||||||
* IfcGeom::Iterator::get() *
|
* IfcGeom::Iterator::get() *
|
||||||
* returns a pointer to the current IfcGeom::Element *
|
* returns a pointer to the current IfcGeom::Element *
|
||||||
* *
|
* *
|
||||||
* IfcGeom::Iterator::next() *
|
* IfcGeom::Iterator::next() *
|
||||||
* returns true iff a following entity is available for a successive call to *
|
* returns true iff a following entity is available for a successive call to *
|
||||||
* IfcGeom::Iterator::get() *
|
* IfcGeom::Iterator::get() *
|
||||||
* *
|
* *
|
||||||
* IfcGeom::Iterator::progress() *
|
* IfcGeom::Iterator::progress() *
|
||||||
* returns an int in [0..100] that indicates the overall progress *
|
* returns an int in [0..100] that indicates the overall progress *
|
||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
#ifndef IFCGEOMITERATOR_H
|
#ifndef IFCGEOMITERATOR_H
|
||||||
@@ -102,6 +102,7 @@ namespace IfcGeom {
|
|||||||
GeometrySerializer* cache_ = nullptr;
|
GeometrySerializer* cache_ = nullptr;
|
||||||
|
|
||||||
std::atomic<bool> finished_{ false };
|
std::atomic<bool> finished_{ false };
|
||||||
|
std::atomic<bool> terminating_{ false };
|
||||||
std::atomic<int> progress_{ 0 };
|
std::atomic<int> progress_{ 0 };
|
||||||
|
|
||||||
std::vector<geometry_conversion_result> tasks_;
|
std::vector<geometry_conversion_result> tasks_;
|
||||||
@@ -148,13 +149,13 @@ namespace IfcGeom {
|
|||||||
std::string unit_name_;
|
std::string unit_name_;
|
||||||
double unit_magnitude_;
|
double unit_magnitude_;
|
||||||
|
|
||||||
ifcopenshell::geometry::taxonomy::point3 bounds_min_;
|
ifcopenshell::geometry::taxonomy::point3 bounds_min_;
|
||||||
ifcopenshell::geometry::taxonomy::point3 bounds_max_;
|
ifcopenshell::geometry::taxonomy::point3 bounds_max_;
|
||||||
|
|
||||||
// Should not be destructed because, destructor is blocking
|
// Should not be destructed because, destructor is blocking
|
||||||
std::future<void> init_future_;
|
std::future<void> init_future_;
|
||||||
|
|
||||||
/// @todo public/private sections all over the place: move all public to the beginning of the class
|
/// @todo public/private sections all over the place: move all public to the beginning of the class
|
||||||
public:
|
public:
|
||||||
void set_cache(GeometrySerializer* cache) { cache_ = cache; }
|
void set_cache(GeometrySerializer* cache) { cache_ = cache; }
|
||||||
|
|
||||||
@@ -302,7 +303,7 @@ namespace IfcGeom {
|
|||||||
break;
|
break;
|
||||||
} // if
|
} // if
|
||||||
} // for
|
} // for
|
||||||
} // while
|
} // while
|
||||||
|
|
||||||
std::future<geometry_conversion_result*> fu = std::async(
|
std::future<geometry_conversion_result*> fu = std::async(
|
||||||
std::launch::async, [this](
|
std::launch::async, [this](
|
||||||
@@ -316,6 +317,10 @@ namespace IfcGeom {
|
|||||||
std::ref(settings_),
|
std::ref(settings_),
|
||||||
&rep);
|
&rep);
|
||||||
|
|
||||||
|
if (terminating_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
threadpool.emplace_back(std::move(fu));
|
threadpool.emplace_back(std::move(fu));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,18 +332,20 @@ namespace IfcGeom {
|
|||||||
|
|
||||||
Logger::SetProduct(boost::none);
|
Logger::SetProduct(boost::none);
|
||||||
|
|
||||||
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(all_processed_elements_.size()) +
|
if (!terminating_) {
|
||||||
" objects) ");
|
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(all_processed_elements_.size()) +
|
||||||
|
" objects) ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes model's bounding box (bounds_min and bounds_max).
|
/// Computes model's bounding box (bounds_min and bounds_max).
|
||||||
/// @note Can take several minutes for large files.
|
/// @note Can take several minutes for large files.
|
||||||
void compute_bounds(bool with_geometry)
|
void compute_bounds(bool with_geometry)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
bounds_min_.components()(i) = std::numeric_limits<double>::infinity();
|
bounds_min_.components()(i) = std::numeric_limits<double>::infinity();
|
||||||
bounds_max_.components()(i) = -std::numeric_limits<double>::infinity();
|
bounds_max_.components()(i) = -std::numeric_limits<double>::infinity();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (with_geometry) {
|
if (with_geometry) {
|
||||||
size_t num_created = 0;
|
size_t num_created = 0;
|
||||||
@@ -381,7 +388,7 @@ namespace IfcGeom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int progress() const {
|
int progress() const {
|
||||||
return progress_;
|
return progress_;
|
||||||
@@ -391,11 +398,11 @@ namespace IfcGeom {
|
|||||||
|
|
||||||
IfcParse::IfcFile* file() const { return ifc_file; }
|
IfcParse::IfcFile* file() const { return ifc_file; }
|
||||||
|
|
||||||
const std::vector<IfcGeom::filter_t>& filters() const { return filters_; }
|
const std::vector<IfcGeom::filter_t>& filters() const { return filters_; }
|
||||||
std::vector<IfcGeom::filter_t>& filters() { return filters_; }
|
std::vector<IfcGeom::filter_t>& filters() { return filters_; }
|
||||||
|
|
||||||
const ifcopenshell::geometry::taxonomy::point3& bounds_min() const { return bounds_min_; }
|
const ifcopenshell::geometry::taxonomy::point3& bounds_min() const { return bounds_min_; }
|
||||||
const ifcopenshell::geometry::taxonomy::point3& bounds_max() const { return bounds_max_; }
|
const ifcopenshell::geometry::taxonomy::point3& bounds_max() const { return bounds_max_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -558,23 +565,23 @@ namespace IfcGeom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Returns what would be the product for the next shape representation
|
/// Returns what would be the product for the next shape representation
|
||||||
/// @todo Double-check and test the impl.
|
/// @todo Double-check and test the impl.
|
||||||
//IfcSchema::IfcProduct* peek_next() const
|
//IfcSchema::IfcProduct* peek_next() const
|
||||||
//{
|
//{
|
||||||
// if (ifcproducts && ifcproduct_iterator + 1 != ifcproducts->end()){
|
// if (ifcproducts && ifcproduct_iterator + 1 != ifcproducts->end()){
|
||||||
// return *(ifcproduct_iterator + 1);
|
// return *(ifcproduct_iterator + 1);
|
||||||
// } else {
|
// } else {
|
||||||
// return 0;
|
// return 0;
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/// @todo Would this be as simple as the following code?
|
/// @todo Would this be as simple as the following code?
|
||||||
//void skip_next() { if (ifcproducts) { ++ifcproduct_iterator; } }
|
//void skip_next() { if (ifcproducts) { ++ifcproduct_iterator; } }
|
||||||
|
|
||||||
/// Moves to the next shape representation, create its geometry, and returns the associated product.
|
/// Moves to the next shape representation, create its geometry, and returns the associated product.
|
||||||
/// Use get() to retrieve the created geometry.
|
/// Use get() to retrieve the created geometry.
|
||||||
const IfcUtil::IfcBaseClass* next() {
|
const IfcUtil::IfcBaseClass* next() {
|
||||||
if (num_threads_ != 1) {
|
if (num_threads_ != 1) {
|
||||||
if (!wait_for_element()) {
|
if (!wait_for_element()) {
|
||||||
@@ -602,10 +609,10 @@ namespace IfcGeom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the representation of the current geometrical entity.
|
/// Gets the representation of the current geometrical entity.
|
||||||
Element* get()
|
Element* get()
|
||||||
{
|
{
|
||||||
auto ret = *task_result_iterator_;
|
auto ret = *task_result_iterator_;
|
||||||
|
|
||||||
// If we want to organize the element considering their hierarchy
|
// If we want to organize the element considering their hierarchy
|
||||||
if (settings_.get<ifcopenshell::geometry::settings::UseElementHierarchy>().get())
|
if (settings_.get<ifcopenshell::geometry::settings::UseElementHierarchy>().get())
|
||||||
@@ -653,8 +660,8 @@ namespace IfcGeom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the native (Open Cascade or CGAL) representation of the current geometrical entity.
|
/// Gets the native (Open Cascade or CGAL) representation of the current geometrical entity.
|
||||||
BRepElement* get_native()
|
BRepElement* get_native()
|
||||||
@@ -666,7 +673,7 @@ namespace IfcGeom {
|
|||||||
ifcopenshell::geometry::taxonomy::matrix4::ptr m4;
|
ifcopenshell::geometry::taxonomy::matrix4::ptr m4;
|
||||||
int parent_id = -1;
|
int parent_id = -1;
|
||||||
std::string instance_type, product_name, product_guid;
|
std::string instance_type, product_name, product_guid;
|
||||||
IfcUtil::IfcBaseEntity* ifc_product = 0;
|
IfcUtil::IfcBaseEntity* ifc_product = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IfcUtil::IfcBaseEntity* ifc_entity = ifc_file->instance_by_id(id)->as<IfcUtil::IfcBaseEntity>();
|
IfcUtil::IfcBaseEntity* ifc_entity = ifc_file->instance_by_id(id)->as<IfcUtil::IfcBaseEntity>();
|
||||||
@@ -773,6 +780,14 @@ namespace IfcGeom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
~Iterator() {
|
~Iterator() {
|
||||||
|
if (num_threads_ != 1) {
|
||||||
|
terminating_ = true;
|
||||||
|
|
||||||
|
if (init_future_.valid()) {
|
||||||
|
init_future_.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (owns_ifc_file) {
|
if (owns_ifc_file) {
|
||||||
delete ifc_file;
|
delete ifc_file;
|
||||||
}
|
}
|
||||||
@@ -787,7 +802,7 @@ namespace IfcGeom {
|
|||||||
delete k;
|
delete k;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& p : all_processed_elements_) {
|
for (auto& p : all_processed_elements_) {
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user