// SPDX-License-Identifier: GPL-2.0-or-later #include #include #include #include #include "async.h" #include "util/statics.h" namespace { // Todo: Replace when C++ gets an .is_ready(). bool is_ready(std::future const &future) { return future.wait_for(std::chrono::seconds(0)) == std::future_status::ready; } // Holds on to asyncs and waits for them to finish at program exit. class AsyncBin { public: static auto const &get() { /* * Using Static to ensure destruction before main() exits, so that lifetimes * of background threads are synchronized with the destruction of statics. */ static Inkscape::Util::Static instance; return instance.get(); } void add(std::future &&future) const { auto g = std::lock_guard(mutables); futures.erase( std::remove_if(futures.begin(), futures.end(), [] (auto const &future) { return is_ready(future); }), futures.end()); futures.emplace_back(std::move(future)); } ~AsyncBin() { drain(); } private: mutable std::mutex mutables; mutable std::vector> futures; auto grab() const { auto g = std::lock_guard(mutables); return std::move(futures); } void drain() const { while (!grab().empty()) {} } }; } // namespace namespace Inkscape { namespace Async { namespace detail { void extend(std::future &&future) { AsyncBin::get().add(std::move(future)); } } // namespace detail } // namespace Async } // namespace Inkscape