flatten 20260225

This commit is contained in:
Timothy Prepscius
2026-02-25 12:39:24 -05:00
commit fa54be052a
315 changed files with 49791 additions and 0 deletions

109
tjp/core/threads/Parallel.cpp Executable file
View File

@@ -0,0 +1,109 @@
// TJP COPYRIGHT HEADER
#include "Parallel.hpp"
#include <limits>
namespace tjp::core::threads {
Parallel::Parallel(int max, int free)
{
start(max, free);
}
Parallel::~Parallel()
{
stop();
}
void Parallel::start(int max, int free)
{
auto lock = lock_of(mutex);
if (running)
return;
running = true;
auto n_ =
std::max(
1,
std::min(
max,
(int)std::thread::hardware_concurrency() - free
)
);
n = n_;
debug_assert(n > 0 && n <= max);
threads = new std::thread[n];
for (auto m=0; m<n; m++)
{
threads[m] = std::thread([this, m]() {
execute(n, m);
});
}
}
void Parallel::execute(size_t n, size_t m)
{
auto lock = lock_of(mutex);
while (running)
{
event.wait(lock, [&](){
return
!running ||
(signal & (SignalBit << m));
});
if (!running)
break;
{
auto unlock = unlock_of(mutex);
f(n, m);
}
signal ^= SignalBit << m;
event.notify_all();
}
event.notify_all();
}
void Parallel::run(F &&f_)
{
auto lock_ = lock_of(oneUser);
auto lock = lock_of(mutex);
f = std::move(f_);
signal = 0;
for (auto i=0; i<n; ++i)
signal |= (1 << i);
event.notify_all();
event.wait(lock, [&]() {
return signal == 0 || !running;
});
}
void Parallel::stop()
{
if (!running)
return;
running = false;
signal = std::numeric_limits<Signal>::max();
event.notify_all();
auto n = std::thread::hardware_concurrency();
for (auto m=0; m<n; ++m)
threads[m].join();
delete[] threads;
}
} // namespace

9
tjp/core/threads/Parallel.h Executable file
View File

@@ -0,0 +1,9 @@
// TJP COPYRIGHT HEADER
#pragma once
namespace tjp::core::threads {
struct Parallel;
} // namespace

44
tjp/core/threads/Parallel.hpp Executable file
View File

@@ -0,0 +1,44 @@
// TJP COPYRIGHT HEADER
#pragma once
#include "Parallel.h"
#include <thread>
#include <tjp/core/threads/Lock.hpp>
#include <tjp/core/threads/Atomic.h>
#include <tjp/core/threads/TestMutex.hpp>
#include <tjp/core/containers/Function.hpp>
namespace tjp::core::threads {
struct Parallel
{
size_t n;
std::thread *threads;
using F = Function<void(size_t n, size_t m)>;
F f;
[[no_unique_address]]
TestMutex oneUser;
Event event;
Event::Mutex mutex;
bool running = false;
using Signal = u128;
static constexpr Signal SignalBit = 1;
Signal signal = 0;
Parallel(int max, int free);
~Parallel();
void start(int max, int free);
void execute(size_t n, size_t m);
void run(F &&f_);
void stop();
} ;
} // namespace

View File

@@ -0,0 +1,140 @@
// TJP COPYRIGHT HEADER
#pragma once
#include <thread>
#include <tjp/core/threads/Lock.hpp>
#include <tjp/core/threads/UnlockGuard.hpp>
#include <tjp/core/threads/Atomic.h>
#include <tjp/core/threads/TestMutex.hpp>
#include <tjp/core/containers/Function.hpp>
#include <queue>
namespace tjp::core::threads {
// DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT
// DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT DRAFT
struct PinnedFutures
{
std::thread thread;
Event::Mutex mutex;
Event event;
std::queue<Function<void()>> events;
bool running = false;
bool is_on_thread()
{
return thread.joinable() &&
(std::this_thread::get_id() == thread.get_id());
}
PinnedFutures(bool start_=true)
{
if (start_)
start();
}
~PinnedFutures()
{
stop();
}
void run()
{
auto lock = lock_of(mutex);
while (running)
{
if (events.empty())
{
event.wait(lock);
continue;
}
auto fn = std::move(events.front());
events.pop();
{
auto unlock = unlock_of(mutex);
fn();
}
}
}
void start()
{
if (running)
return;
running = true;
thread = std::thread([this]() { run(); });
}
void stop()
{
{
auto lock = lock_of(mutex);
running = false;
}
event.notify_all();
if (thread.joinable())
thread.join();
}
template<typename V>
Future<V> on_(Future<V> &f0)
{
Promise<V> p;
auto swizzle = f0.then([this, p](auto &&f) {
auto lock = lock_of(mutex);
events.push([p, f=std::move(f)]() {
auto p_ = p;
auto f_ = f;
p_.consume([&](auto &&f) { return f.get(); }, f_);
});
event.notify_one();
});
return p.get_future().then([swizzle](auto &&f1) {
return f1.get();
});
}
template<typename F>
auto run_(F &&f)
{
using R = decltype(f());
Promise<R> p;
{
auto lock = lock_of(mutex);
events.push([&]() { p.consume(f); });
event.notify_one();
}
return p.get_future().get();
}
template<typename V>
Future<V> on(Future<V> &f)
{
return on_(f);
}
template<typename F>
auto run(F &&f)
{
if (is_on_thread())
return f();
return run_(std::forward<F>(f));
}
} ;
} // namespace