vendredi 25 novembre 2016

Compilation error when passing functional object and its arguments to std::thread constructor

I'm trying to compile the following code, but on the line threads[i] = std::thread(find_elements[i], block_start, block_end, match); the std::thread object cannot be constructed with given arguments. The exact error produced by clang++ version 3.9.1 is the following.

template <typename Iterator, typename MatchType>
Iterator parallel_find(Iterator first, Iterator last, MatchType match)
{
  class find_element
  {
  public:
    void operator()(Iterator begin, Iterator end, MatchType match)
    {
      try
      {
        while (begin != end)
        {
          if (*begin == match)
          {
            result_.set_value(begin);
            is_found_ = true;
            return;
          }
          ++begin;
        }
        result_.set_value(end);
      }
      catch(...)
      {
        result_.set_exception(std::current_exception());
      }
    }

    Iterator get() { return result_.get_future().get(); }
    bool is_found() const { return is_found_; }

  private:
    std::promise<Iterator> result_;
    bool is_found_ = false;
  };

  const unsigned length = std::distance(first, last);

  if (0 == length) return last;

  const unsigned min_per_thread = 25;
  const unsigned max_threads = (length + min_per_thread - 1) / min_per_thread;
  const unsigned hardware_threads = std::thread::hardware_concurrency();
  const unsigned num_threads = std::min(
        hardware_threads != 0 ? hardware_threads : 2, max_threads);
  const unsigned block_size = length / num_threads;

  std::vector<std::thread> threads(num_threads - 1);
  std::vector<find_element> find_elements(num_threads);

  {
    join_threads joiner(threads);
    Iterator block_start = first;
    for (unsigned i = 0; i < num_threads - 1; ++i)
    {
      Iterator block_end = block_start;
      std::advance(block_end, block_size);
      threads[i] = std::thread(find_elements[i], block_start, block_end, match);
      block_start = block_end;
    }

    find_elements[num_threads - 1](block_start, last, match);
  }

  for (unsigned i = 0; i < num_threads - 1; ++i)
  {
    if (find_elements[i].is_found())
    {
      return find_elements[i].get();
    }
  }

  return find_elements[num_threads - 1].get();
}

Aucun commentaire:

Enregistrer un commentaire