57 lines
1.7 KiB
C++
57 lines
1.7 KiB
C++
#pragma once
|
|
|
|
#include "../../generator/generator.h"
|
|
#include "AbstractVectorFactory.h"
|
|
#include "fill_with.h"
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <thread>
|
|
|
|
namespace atlas::collection {
|
|
namespace {
|
|
void join_thread(std::thread& t)
|
|
{
|
|
t.join();
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
class MultiThreadedVectorFactory : public AbstractVectorFactory<T> {
|
|
|
|
public:
|
|
using Self = MultiThreadedVectorFactory<T>;
|
|
|
|
MultiThreadedVectorFactory(std::function<std::unique_ptr<generator::Generator<T>>()> 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<T>& v) -> void override final
|
|
{
|
|
std::vector<std::thread> 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<int>::iterator from, std::vector<int>::iterator to)
|
|
{
|
|
detail::fill_with(from, to, [g = m_gen()]() { return g->next(); });
|
|
}
|
|
|
|
std::function<std::unique_ptr<generator::Generator<T>>()> m_gen;
|
|
size_t m_threads;
|
|
};
|
|
}
|