Files
core_misc/tjp/core/threads/Parallel.cpp
Timothy Prepscius fa54be052a flatten 20260225
2026-02-25 12:39:24 -05:00

110 lines
1.5 KiB
C++
Executable File

// 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