IfcGeom: make no-parallel-mapping and permissive-shape-reuse usable with threads #6712

Iterator::initialize() disabled mapping caching whenever the iterator
was constructed with more than one thread, including in
no-parallel-mapping mode where all mapping happens upfront on the
calling thread. Without the cache, the shared representation of a
mapped item was remapped once per product (9210 times in the first
attachment of #6712), so initialize() appeared to hang, and the
permissive-shape-reuse folding, which merges tasks by cached item
pointer identity, silently never folded. Both effects were reported in
the issue thread.

Caching is now only disabled when parallel mapping will actually run
in the worker threads. In no-parallel-mapping mode the iterator falls
back to sequential processing, since cache-shared taxonomy items are
not yet safe to convert concurrently (cf. the immutability todo).
Additionally, permissive-shape-reuse now implies no-parallel-mapping
inside the iterator itself, mirroring what IfcConvert already forced,
so library users get the folding without knowing about the coupling.

With this, the reporter's configuration (permissive-shape-reuse with
hardware_concurrency threads) completes the 12 MB attachment in 1.4 s
instead of hanging; output is identical to the previously working
single-threaded configuration.

Generated with the assistance of an AI coding tool.
This commit is contained in:
Petru Conduraru
2026-07-21 14:41:22 +03:00
parent 484b2e9930
commit eca82d1d18
+18 -2
View File
@@ -23,10 +23,26 @@ bool IfcGeom::Iterator::initialize() {
}
time_points[0] = high_resolution_clock::now();
if (settings_.get<ifcopenshell::geometry::settings::PermissiveShapeReuse>().get() && !settings_.get<ifcopenshell::geometry::settings::NoParallelMapping>().get()) {
// Folding tasks based on permissive shape reuse requires the upfront mapping
settings_.get<ifcopenshell::geometry::settings::NoParallelMapping>().value = true;
logger_.Notice("SYS", 36, "Enabled no-parallel-mapping due to permissive-shape-reuse");
}
std::vector<ifcopenshell::geometry::geometry_conversion_task> reps;
if (num_threads_ != 1) {
// @todo this shouldn't be necessary with properly immutable taxonomy items
converter_->mapping()->use_caching() = false;
if (!settings_.get<ifcopenshell::geometry::settings::NoParallelMapping>().get()) {
// @todo this shouldn't be necessary with properly immutable taxonomy items
converter_->mapping()->use_caching() = false;
} else {
// The upfront mapping below runs on this thread with caching, which is
// what makes instance reuse (and the permissive-shape-reuse folding)
// effective, but cache-shared taxonomy items cannot be converted
// concurrently yet, cf. the immutability @todo above
num_threads_ = 1;
logger_.Notice("SYS", 37, "Processing sequentially due to no-parallel-mapping");
}
}
try {
converter_->mapping()->get_representations(reps, filters_);