dds-bridge-sys 3.3.0

Generated bindings to DDS, the double dummy solver for bridge
Documentation
/*
   DDS, a bridge double dummy solver.

   Copyright (C) 2006-2014 by Bo Haglund /
   2014-2018 by Bo Haglund & Soren Hein.

   See LICENSE and README.
*/

#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;
}