From eca82d1d186c549b81c032de7416d9f970c1f84e Mon Sep 17 00:00:00 2001 From: Petru Conduraru Date: Tue, 21 Jul 2026 14:41:22 +0300 Subject: [PATCH] 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. --- src/ifcgeom/Iterator.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ifcgeom/Iterator.cpp b/src/ifcgeom/Iterator.cpp index 914d55f20a..c334edb969 100644 --- a/src/ifcgeom/Iterator.cpp +++ b/src/ifcgeom/Iterator.cpp @@ -23,10 +23,26 @@ bool IfcGeom::Iterator::initialize() { } time_points[0] = high_resolution_clock::now(); + + if (settings_.get().get() && !settings_.get().get()) { + // Folding tasks based on permissive shape reuse requires the upfront mapping + settings_.get().value = true; + logger_.Notice("SYS", 36, "Enabled no-parallel-mapping due to permissive-shape-reuse"); + } + std::vector reps; if (num_threads_ != 1) { - // @todo this shouldn't be necessary with properly immutable taxonomy items - converter_->mapping()->use_caching() = false; + if (!settings_.get().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_);