finish up

This commit is contained in:
Thomas Krijnen
2021-11-12 09:54:08 +01:00
parent 72206bc441
commit 6d725f60fa
2 changed files with 68 additions and 53 deletions
+1 -9
View File
@@ -904,10 +904,6 @@ int main(int argc, char** argv) {
Logger::Notice("Using " + std::to_string(num_threads) + " threads"); Logger::Notice("Using " + std::to_string(num_threads) + " threads");
} }
if (!quiet && num_threads > 1) {
Logger::Status("Creating geometry...");
}
if (vmap.count("log-file")) { if (vmap.count("log-file")) {
Logger::SetOutput(quiet ? nullptr : &cout_, &log_fs); Logger::SetOutput(quiet ? nullptr : &cout_, &log_fs);
} else { } else {
@@ -1085,11 +1081,7 @@ int main(int argc, char** argv) {
int old_progress = quiet ? 0 : -1; int old_progress = quiet ? 0 : -1;
if (!quiet) { if (!quiet) {
if (num_threads == 1) { Logger::Status("Creating geometry...");
Logger::Status("Creating geometry...");
} else {
Logger::Status("Writing geometry...");
}
} }
// The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next() // The functions IfcGeom::Iterator::get() and IfcGeom::Iterator::next()
+66 -43
View File
@@ -114,12 +114,19 @@ namespace IfcGeom {
class MAKE_TYPE_NAME(IteratorImplementation_) : public IteratorImplementation { class MAKE_TYPE_NAME(IteratorImplementation_) : public IteratorImplementation {
private: private:
std::atomic<int> progress_; std::atomic<bool> finished_ = false;
std::atomic<int> progress_ = 0;
std::vector<geometry_conversion_task> tasks_; std::vector<geometry_conversion_task> tasks_;
std::vector<IfcGeom::Element*> all_processed_elements_;
std::vector<IfcGeom::BRepElement*> all_processed_native_elements_; std::list<IfcGeom::Element*> all_processed_elements_;
typename std::vector<IfcGeom::Element*>::const_iterator task_result_iterator_; std::list<IfcGeom::BRepElement*> all_processed_native_elements_;
typename std::vector<IfcGeom::BRepElement*>::const_iterator native_task_result_iterator_;
typename std::list<IfcGeom::Element*>::const_iterator task_result_iterator_;
typename std::list<IfcGeom::BRepElement*>::const_iterator native_task_result_iterator_;
std::mutex element_ready_mutex_;
bool task_result_ptr_initialized = false;
size_t async_elements_returned_ = 0;
MAKE_TYPE_NAME(IteratorImplementation_)(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I MAKE_TYPE_NAME(IteratorImplementation_)(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
MAKE_TYPE_NAME(IteratorImplementation_)& operator=(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I MAKE_TYPE_NAME(IteratorImplementation_)& operator=(const MAKE_TYPE_NAME(IteratorImplementation_)&); // N/I
@@ -240,6 +247,10 @@ namespace IfcGeom {
initialization_outcome_ = !tasks_.empty(); initialization_outcome_ = !tasks_.empty();
init_future_ = std::async(std::launch::async, [this]() { process_concurrently(); }); init_future_ = std::async(std::launch::async, [this]() { process_concurrently(); });
// wait for the first element, because after init(), get() can be called.
// so the element conversion must succeed
initialization_outcome_ = wait_for_element();
} else { } else {
initialization_outcome_ = create(); initialization_outcome_ = create();
} }
@@ -275,6 +286,23 @@ namespace IfcGeom {
} }
} }
size_t processed_ = 0;
void process_finished_rep(geometry_conversion_task* rep) {
std::lock_guard<std::mutex> lk(element_ready_mutex_);
all_processed_elements_.insert(all_processed_elements_.end(), rep->elements.begin(), rep->elements.end());
all_processed_native_elements_.insert(all_processed_native_elements_.end(), rep->breps.begin(), rep->breps.end());
if (!task_result_ptr_initialized) {
task_result_iterator_ = all_processed_elements_.begin();
native_task_result_iterator_ = all_processed_native_elements_.begin();
task_result_ptr_initialized = true;
}
progress_ = ++processed_ * 100 / tasks_.size();
}
void process_concurrently() { void process_concurrently() {
size_t conc_threads = num_threads_; size_t conc_threads = num_threads_;
if (conc_threads > tasks_.size()) { if (conc_threads > tasks_.size()) {
@@ -287,12 +315,7 @@ namespace IfcGeom {
kernel_pool.push_back(new MAKE_TYPE_NAME(Kernel)(kernel)); kernel_pool.push_back(new MAKE_TYPE_NAME(Kernel)(kernel));
} }
std::vector<std::future<void>> threadpool; std::vector<std::future<geometry_conversion_task*>> threadpool;
int old_progress = -1;
int processed = 0;
Logger::ProgressBar(0);
for (auto& rep : tasks_) { for (auto& rep : tasks_) {
MAKE_TYPE_NAME(Kernel)* K = nullptr; MAKE_TYPE_NAME(Kernel)* K = nullptr;
@@ -302,18 +325,11 @@ namespace IfcGeom {
while (threadpool.size() == conc_threads) { while (threadpool.size() == conc_threads) {
for (int i = 0; i < (int)threadpool.size(); i++) { for (int i = 0; i < (int)threadpool.size(); i++) {
std::future<void> &fu = threadpool[i]; auto& fu = threadpool[i];
std::future_status status; std::future_status status;
status = fu.wait_for(std::chrono::seconds(0)); status = fu.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) { if (status == std::future_status::ready) {
fu.get(); process_finished_rep(fu.get());
processed += 1;
progress_ = processed * 50 / tasks_.size();
if (progress_ != old_progress) {
Logger::ProgressBar(progress_);
old_progress = progress_;
}
std::swap(threadpool[i], threadpool.back()); std::swap(threadpool[i], threadpool.back());
threadpool.pop_back(); threadpool.pop_back();
@@ -324,12 +340,13 @@ namespace IfcGeom {
} // for } // for
} // while } // while
std::future<void> fu = std::async( std::future<geometry_conversion_task*> fu = std::async(
std::launch::async, [this]( std::launch::async, [this](
IfcGeom::MAKE_TYPE_NAME(Kernel)* kernel, IfcGeom::MAKE_TYPE_NAME(Kernel)* kernel,
const IfcGeom::IteratorSettings& settings, const IfcGeom::IteratorSettings& settings,
geometry_conversion_task* rep) { geometry_conversion_task* rep) {
return this->create_element_(kernel, settings, rep); this->create_element_(kernel, settings, rep);
return rep;
}, },
K, K,
std::ref(settings), std::ref(settings),
@@ -338,24 +355,11 @@ namespace IfcGeom {
threadpool.emplace_back(std::move(fu)); threadpool.emplace_back(std::move(fu));
} }
for (std::future<void> &fu : threadpool) { for (auto& fu : threadpool) {
fu.get(); process_finished_rep(fu.get());
processed += 1;
progress_ = processed * 100 / tasks_.size();
if (progress_ / 2 != old_progress) {
Logger::ProgressBar(progress_ / 2);
old_progress = progress_ / 2;
}
} }
for (auto& rep : tasks_) { finished_ = true;
all_processed_elements_.insert(all_processed_elements_.end(), rep.elements.begin(), rep.elements.end());
all_processed_native_elements_.insert(all_processed_native_elements_.end(), rep.breps.begin(), rep.breps.end());
}
task_result_iterator_ = all_processed_elements_.begin();
native_task_result_iterator_ = all_processed_native_elements_.begin();
Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(all_processed_elements_.size()) + Logger::Status("\rDone creating geometry (" + boost::lexical_cast<std::string>(all_processed_elements_.size()) +
" objects) "); " objects) ");
@@ -874,6 +878,24 @@ namespace IfcGeom {
} }
} }
bool wait_for_element() {
while (true) {
size_t s;
{
std::lock_guard<std::mutex> lk(element_ready_mutex_);
s = all_processed_elements_.size();
}
if (s > async_elements_returned_) {
++async_elements_returned_;
return true;
} else if (finished_) {
return false;
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
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.
@@ -893,13 +915,14 @@ namespace IfcGeom {
/// Use get() to retrieve the created geometry. /// Use get() to retrieve the created geometry.
IfcUtil::IfcBaseClass* next() { IfcUtil::IfcBaseClass* next() {
if (num_threads_ != 1) { if (num_threads_ != 1) {
if (!wait_for_element()) {
return nullptr;
}
task_result_iterator_++; task_result_iterator_++;
native_task_result_iterator_++; native_task_result_iterator_++;
if (task_result_iterator_ == all_processed_elements_.end()) {
return nullptr; return (*task_result_iterator_)->product();
} else {
return (*task_result_iterator_)->product();
}
} else { } else {
// Increment the iterator over the list of products using the current // Increment the iterator over the list of products using the current
// shape representation // shape representation