#include "parallel_boards.hpp"
#include <algorithm>
#include <atomic>
#include <thread>
#include <vector>
#include <api/dll.h>
auto parallel_all_boards_n(
const int count,
const int worker_cap,
const std::function<int(int worker_id, int bno)>& process_board) -> int
{
if (count <= 0)
{
return RETURN_NO_FAULT;
}
int workers = worker_cap;
if (workers <= 0)
{
const unsigned hw = std::thread::hardware_concurrency();
workers = hw > 0 ? static_cast<int>(hw) : 1;
}
workers = std::max(1, std::min(workers, count));
if (workers == 1)
{
for (int bno = 0; bno < count; ++bno)
{
const int rc = process_board(0, bno);
if (rc != RETURN_NO_FAULT)
{
return rc;
}
}
return RETURN_NO_FAULT;
}
std::atomic<int> next{0};
std::atomic<int> first_error{RETURN_NO_FAULT};
auto worker = [&](const int worker_id) {
for (;;)
{
const int bno = next.fetch_add(1, std::memory_order_relaxed);
if (bno >= count || first_error.load(std::memory_order_relaxed) != RETURN_NO_FAULT)
{
break;
}
const int rc = process_board(worker_id, bno);
if (rc != RETURN_NO_FAULT)
{
int expected = RETURN_NO_FAULT;
first_error.compare_exchange_strong(
expected, rc, std::memory_order_relaxed);
break;
}
}
};
std::vector<std::thread> threads;
threads.reserve(static_cast<unsigned>(workers));
try
{
for (int t = 0; t < workers; ++t)
{
threads.emplace_back(worker, t);
}
}
catch (...)
{
for (auto & th : threads)
{
if (th.joinable())
{
th.join();
}
}
throw;
}
for (auto & th : threads)
{
th.join();
}
const int err = first_error.load(std::memory_order_relaxed);
return err != RETURN_NO_FAULT ? err : RETURN_NO_FAULT;
}