| 187 | } |
| 188 | |
| 189 | void IfcGeom::Iterator::process_concurrently() { |
| 190 | size_t conc_threads = num_threads_; |
| 191 | if (conc_threads > tasks_.size()) { |
| 192 | conc_threads = tasks_.size(); |
| 193 | } |
| 194 | |
| 195 | kernel_pool.reserve(conc_threads); |
| 196 | for (unsigned i = 0; i < conc_threads; ++i) { |
| 197 | kernel_pool.push_back(new ifcopenshell::geometry::Converter(std::unique_ptr<ifcopenshell::geometry::kernels::AbstractKernel>(converter_->kernel()->clone()), ifc_file, settings_)); |
| 198 | } |
| 199 | |
| 200 | std::vector<std::future<geometry_conversion_result*>> threadpool; |
| 201 | |
| 202 | for (auto& rep : tasks_) { |
| 203 | ifcopenshell::geometry::Converter* K = nullptr; |
| 204 | if (threadpool.size() < kernel_pool.size()) { |
| 205 | K = kernel_pool[threadpool.size()]; |
| 206 | } |
| 207 | |
| 208 | while (threadpool.size() == conc_threads) { |
| 209 | for (int i = 0; i < (int)threadpool.size(); i++) { |
| 210 | auto& fu = threadpool[i]; |
| 211 | std::future_status status; |
| 212 | status = fu.wait_for(std::chrono::seconds(0)); |
| 213 | if (status == std::future_status::ready) { |
| 214 | process_finished_rep(fu.get()); |
| 215 | |
| 216 | std::swap(threadpool[i], threadpool.back()); |
| 217 | threadpool.pop_back(); |
| 218 | std::swap(kernel_pool[i], kernel_pool.back()); |
| 219 | K = kernel_pool.back(); |
| 220 | break; |
| 221 | } // if |
| 222 | } // for |
| 223 | } // while |
| 224 | |
| 225 | std::future<geometry_conversion_result*> fu = std::async( |
| 226 | std::launch::async, [this]( |
| 227 | ifcopenshell::geometry::Converter* kernel, |
| 228 | ifcopenshell::geometry::Settings settings, |
| 229 | geometry_conversion_result* rep) { |
| 230 | // Catch exceptions to be safe from freezing the iterator. |
| 231 | try { |
| 232 | this->create_element_(kernel, settings, rep); |
| 233 | } catch (const std::exception& e) { |
| 234 | Logger::Error( |
| 235 | std::string("Exception '") + e.what() + |
| 236 | std::string("' occurred while iterator was creating a shape: "), |
| 237 | rep->item->instance |
| 238 | ); |
| 239 | had_error_processing_elements_ = true; |
| 240 | } catch (...) { |
| 241 | Logger::Error( |
| 242 | "Unknown exception occurred while iteartor was creating a shape: ", |
| 243 | rep->item->instance |
| 244 | ); |
| 245 | had_error_processing_elements_ = true; |
| 246 | } |