#pragma once #include "../../generator/generator.h" #include "AbstractVectorFactory.h" #include "fill_with.h" #include #include #include namespace atlas::collection { namespace { void join_thread(std::thread& t) { t.join(); } } template class MultiThreadedVectorFactory : public AbstractVectorFactory { public: using Self = MultiThreadedVectorFactory; MultiThreadedVectorFactory(std::function>()> generator_factory, size_t const nthreads) : m_gen { std::move(generator_factory) } , m_threads { nthreads } { } MultiThreadedVectorFactory(MultiThreadedVectorFactory const&) = delete; MultiThreadedVectorFactory(MultiThreadedVectorFactory&&) = delete; MultiThreadedVectorFactory& operator=(MultiThreadedVectorFactory const&) = delete; MultiThreadedVectorFactory& operator=(MultiThreadedVectorFactory&&) = delete; auto fill(std::vector& v) -> void override final { std::vector threads; size_t const slice { v.size() / m_threads }; auto pos = v.begin(); for (size_t i = 0; i < m_threads; ++i, pos += slice) { threads.emplace_back([this, from = pos, to = pos + slice] { this->worker(from, to); }); } worker(pos, v.end()); std::for_each(threads.begin(), threads.end(), join_thread); } private: void worker(std::vector::iterator from, std::vector::iterator to) { detail::fill_with(from, to, [g = m_gen()]() { return g->next(); }); } std::function>()> m_gen; size_t m_threads; }; }