From 40937b3c72a00d9600ed33e3024fa4418db42a50 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 9 Jul 2019 16:00:58 +0200 Subject: [PATCH] Write progress for threaded conversion --- src/ifcconvert/IfcConvert.cpp | 46 ++++++++++++++------- src/ifcgeom/IfcGeomIteratorImplementation.h | 28 ++++++++++++- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index bca7396422..9141e31f41 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -62,8 +62,9 @@ #include #include #endif -// C++11 header: + #include +#include #if defined(_MSC_VER) && defined(_UNICODE) typedef std::wstring path_t; @@ -520,7 +521,7 @@ int main(int argc, char** argv) { } } - Logger::SetOutput(&cout_, &log_stream); + Logger::SetOutput(quiet ? nullptr : &cout_, &log_stream); Logger::Verbosity(verbose ? Logger::LOG_NOTICE : Logger::LOG_ERROR); path_t output_temp_filename = output_filename + IfcUtil::path::from_utf8(TEMP_FILE_EXTENSION); @@ -734,7 +735,18 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - IfcGeom::Iterator context_iterator(settings, ifc_file, filter_funcs, num_threads); + if (num_threads == 0) { + num_threads = std::thread::hardware_concurrency(); + Logger::Notice("Using " + std::to_string(num_threads) + " threads"); + } + + if (!quiet && num_threads > 1) { + Logger::Status("Creating geometry..."); + } + + Logger::SetOutput(quiet ? nullptr : &cout_, &log_stream); + + IfcGeom::Iterator context_iterator(settings, ifc_file, filter_funcs, num_threads); if (!context_iterator.initialize()) { /// @todo It would be nice to know and print separate error prints for a case where we found no entities /// and for a case we found no entities that satisfy our filtering criteria. @@ -788,7 +800,11 @@ int main(int argc, char** argv) { } if (!quiet) { - Logger::Status("Creating geometry..."); + if (num_threads == 1) { + Logger::Status("Creating geometry..."); + } else { + Logger::Status("Writing geometry..."); + } } // The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next() @@ -819,13 +835,13 @@ int main(int argc, char** argv) { if (quiet) { const int progress = context_iterator.progress(); for (; old_progress < progress; ++old_progress) { - std::cout << "."; + cout_ << "."; if (stderr_progress) - std::cerr << "."; + cerr_ << "."; } - std::cout << std::flush; + cout_ << std::flush; if (stderr_progress) - std::cerr << std::flush; + cerr_ << std::flush; } else { const int progress = context_iterator.progress() / 2; if (old_progress != progress) Logger::ProgressBar(progress); @@ -836,15 +852,17 @@ int main(int argc, char** argv) { if (!no_progress && quiet) { for (; old_progress < 100; ++old_progress) { - std::cout << "."; + cout_ << "."; if (stderr_progress) - std::cerr << "."; + cerr_ << "."; + } + cout_ << std::flush; + if (stderr_progress) { + cerr_ << std::flush; } - std::cout << std::flush; - if (stderr_progress) - std::cerr << std::flush; } else { - Logger::Status("\rDone creating geometry (" + boost::lexical_cast(num_created) + + const std::string task = ((num_threads == 1) ? "creating" : "writing"); + Logger::Status("\rDone " + task + " geometry (" + boost::lexical_cast(num_created) + " objects) "); } diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.h b/src/ifcgeom/IfcGeomIteratorImplementation.h index 5583dd0a14..b36ec75c9a 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.h +++ b/src/ifcgeom/IfcGeomIteratorImplementation.h @@ -417,8 +417,16 @@ namespace IfcGeom { std::vector> threadpool; + int old_progress = -1; + int processed = 0; + + Logger::ProgressBar(0); + for (auto& rep : tasks_) { - auto K = kernel_pool[threadpool.size()]; + MAKE_TYPE_NAME(Kernel)* K = nullptr; + if (threadpool.size() < kernel_pool.size()) { + K = kernel_pool[threadpool.size()]; + } while (threadpool.size() == conc_threads) { for (int i = 0; i < (int)threadpool.size(); i++) { @@ -427,6 +435,14 @@ namespace IfcGeom { status = fu.wait_for(std::chrono::seconds(0)); if (status == std::future_status::ready) { fu.get(); + + processed += 1; + const int progress = processed * 50 / tasks_.size(); + if (progress != old_progress) { + Logger::ProgressBar(progress); + old_progress = progress; + } + std::swap(threadpool[i], threadpool.back()); threadpool.pop_back(); std::swap(kernel_pool[i], kernel_pool.back()); @@ -442,6 +458,13 @@ namespace IfcGeom { for (std::future &fu : threadpool) { fu.get(); + + processed += 1; + const int progress = processed * 50 / tasks_.size(); + if (progress != old_progress) { + Logger::ProgressBar(progress); + old_progress = progress; + } } for (auto& rep : tasks_) { @@ -451,6 +474,9 @@ namespace IfcGeom { task_result_iterator_ = all_processed_elements_.begin(); native_task_result_iterator_ = all_processed_native_elements_.begin(); + + Logger::Status("\rDone creating geometry (" + boost::lexical_cast(all_processed_elements_.size()) + + " objects) "); } /// Computes model's bounding box (bounds_min and bounds_max).