Initial commit

This commit is contained in:
Alexander Kobjolke 2025-03-13 22:36:51 +01:00
commit 4f4397b3e1
48 changed files with 2002 additions and 0 deletions

View file

@ -0,0 +1,20 @@
// -*- mode: c++ -*-
#pragma once
#include <memory>
#include <vector>
namespace atlas::collection {
template <typename T>
class VectorFactory {
public:
using base_type = VectorFactory<T>;
using value_type = std::vector<T>;
using product_type = std::shared_ptr<value_type>;
virtual ~VectorFactory() = default;
[[nodiscard]] virtual auto createAndFillVector(size_t const) -> product_type = 0;
};
}

View file

@ -0,0 +1,39 @@
#pragma once
#include "../../time/time.h"
#include "../VectorFactory.h"
#include <chrono>
#include <iostream>
namespace atlas::collection::decorator {
template <typename T>
class MeasuredVectorFactory : public VectorFactory<T> {
public:
using decorated_type = VectorFactory<T>;
using decorated_ptr = std::unique_ptr<decorated_type>;
using stopwatch_ptr = std::unique_ptr<time::Timer<std::chrono::milliseconds>>;
MeasuredVectorFactory(stopwatch_ptr stopwatch, decorated_ptr decorated)
: m_stopwatch { std::move(stopwatch) }
, m_decorated { std::move(decorated) }
{
}
auto createAndFillVector(size_t const size) -> typename decorated_type::product_type override final
{
return logTimerResult(m_stopwatch->measure(
[this, size] { return m_decorated->createAndFillVector(size); }));
}
private:
template <typename Result>
auto logTimerResult(Result&& result) const
{
std::cout << "Duration: " << result.duration.count() << "ms\n";
return result.value;
}
stopwatch_ptr m_stopwatch;
decorated_ptr m_decorated;
};
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "../VectorFactory.h"
namespace atlas::collection {
template <typename T>
class AbstractVectorFactory : public VectorFactory<T> {
public:
using base_type = VectorFactory<T>;
auto createAndFillVector(size_t const size) -> typename base_type::product_type override final
{
auto result = std::make_shared<std::vector<T>>(size);
fill(*result);
return result;
}
virtual void fill(std::vector<T>&) = 0;
};
}

View file

@ -0,0 +1,34 @@
#pragma once
#include "../../generator/generator.h"
#include "AbstractVectorFactory.h"
#include <algorithm>
#include <execution>
namespace atlas::collection {
template <typename T>
class AutoThreadedVectorFactory : public AbstractVectorFactory<T> {
public:
AutoThreadedVectorFactory(std::function<std::unique_ptr<generator::Generator<T>>()> generator_factory)
: m_gen { std::move(generator_factory) }
{
}
AutoThreadedVectorFactory(AutoThreadedVectorFactory const&) = delete;
AutoThreadedVectorFactory(AutoThreadedVectorFactory&&) = delete;
AutoThreadedVectorFactory& operator=(AutoThreadedVectorFactory const&) = delete;
AutoThreadedVectorFactory& operator=(AutoThreadedVectorFactory&&) = delete;
auto fill(std::vector<T>& v) -> void override final
{
std::for_each(std::execution::par_unseq, v.begin(), v.end(), [this](auto& v) {
static thread_local auto gen { m_gen() };
v = gen->next();
});
}
private:
std::function<std::unique_ptr<generator::Generator<T>>()> m_gen;
};
}

View file

@ -0,0 +1,57 @@
#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;
};
}

View file

@ -0,0 +1,31 @@
#pragma once
#include "../../generator/generator.h"
#include "AbstractVectorFactory.h"
#include "fill_with.h"
#include <algorithm>
namespace atlas::collection {
template <typename T>
class SingleThreadedVectorFactory : public AbstractVectorFactory<T> {
public:
SingleThreadedVectorFactory(std::unique_ptr<generator::Generator<T>> generator)
: m_gen { std::move(generator) }
{
}
SingleThreadedVectorFactory(SingleThreadedVectorFactory const&) = delete;
SingleThreadedVectorFactory(SingleThreadedVectorFactory&&) = delete;
SingleThreadedVectorFactory& operator=(SingleThreadedVectorFactory const&) = delete;
SingleThreadedVectorFactory& operator=(SingleThreadedVectorFactory&&) = delete;
auto fill(std::vector<T>& v) -> void override final
{
detail::fill_with(v.begin(), v.end(), [this]() { return m_gen->next(); });
}
private:
std::unique_ptr<generator::Generator<T>> m_gen;
};
}

View file

@ -0,0 +1,12 @@
#pragma once
#include <algorithm>
namespace atlas::collection::detail {
template <typename Iter, typename F>
void fill_with(Iter start, Iter end, F f)
{
std::for_each(start, end, [g = std::move(f)](auto& v) { v = g(); });
}
}