Repository: apache/arrow
File: cpp/src/arrow/util/thread_pool.h (C/C++)

Code before:
ARROW_EXPORT ThreadPool* GetCpuThreadPool();

/// \brief Potentially run an async operation serially (if use_threads is false)
/// \see RunSerially
///
/// If `use_threads` is true, the global CPU executor is used.
/// If `use_threads` is false, a temporary SerialExecutor is used.
/// `get_future` is called (from this thread) with the chosen executor and must
/// return a future that will eventually finish. This function returns once the
/// future has finished.
template <typename Fut, typename ValueType = typename Fut::ValueType>
typename Fut::SyncType RunSynchronously(FnOnce<Fut(Executor*)> get_future,
                                        bool use_threads) {
  if (use_threads) {
    auto fut = std::move(get_future)(GetCpuThreadPool());
    return FutureToSync(fut);
  } else {
    return SerialExecutor::RunInSerialExecutor<ValueType>(std::move(get_future));
  }
}

/// \brief Potentially iterate an async generator serially (if use_threads is false)
///   using a potentially custom Executor
/// \see IterateGenerator
///
/// If `use_threads` is true, the global CPU executor will be used.  Each call to
///   the iterator will simply wait until the next item is available.  Tasks may run in
///   the background between calls.
///
/// If `use_threads` is false, the calling thread only will be used.  Each call to
///   the iterator will use the calling thread to do enough work to generate one item.
///   Tasks will be left in a queue until the next call and no work will be done between
///   calls.
///
/// If `executor` is null, then the default CPU thread pool will be used.
/// If `executor` is not null, then it will be used.
template <typename T>
Iterator<T> IterateSynchronously(
    FnOnce<Result<std::function<Future<T>()>>(Executor*)> get_gen, bool use_threads,
    Executor* executor) {
  if (use_threads) {
    auto used_executor = executor != NULLPTR ? executor : GetCpuThreadPool();
    auto maybe_gen = std::move(get_gen)(used_executor);
    if (!maybe_gen.ok()) {
      return MakeErrorIterator<T>(maybe_gen.status());
    }
    return MakeGeneratorIterator(*maybe_gen);
  } else {
    return SerialExecutor::IterateGenerator(std::move(get_gen));
  }
}

Review comment (suggestion):
```suggestion
/// If `use_threads` is true, the custom executor or, if null, the global CPU executor will be used.  Each call to
```

Code after:

/// \brief Potentially run an async operation serially (if use_threads is false)
/// \see RunSerially
///
/// If `use_threads` is true, the global CPU executor is used.
/// If `use_threads` is false, a temporary SerialExecutor is used.
/// `get_future` is called (from this thread) with the chosen executor and must
/// return a future that will eventually finish. This function returns once the
/// future has finished.
template <typename Fut, typename ValueType = typename Fut::ValueType>
typename Fut::SyncType RunSynchronously(FnOnce<Fut(Executor*)> get_future,
                                        bool use_threads) {
  if (use_threads) {
    auto fut = std::move(get_future)(GetCpuThreadPool());
    return FutureToSync(fut);
  } else {
    return SerialExecutor::RunInSerialExecutor<ValueType>(std::move(get_future));
  }
}

/// \brief Potentially iterate an async generator serially (if use_threads is false)
///   using a potentially custom Executor
/// \see IterateGenerator
///
/// If `use_threads` is true, the custom executor or, if null,
///   the global CPU executor will be used.  Each call to
///   the iterator will simply wait until the next item is available.  Tasks may run in
///   the background between calls.
///
/// If `use_threads` is false, the calling thread only will be used.  Each call to
///   the iterator will use the calling thread to do enough work to generate one item.
///   Tasks will be left in a queue until the next call and no work will be done between
///   calls.
template <typename T>
Iterator<T> IterateSynchronously(
    FnOnce<Result<std::function<Future<T>()>>(Executor*)> get_gen, bool use_threads,
    Executor* executor) {
  if (use_threads) {
    auto used_executor = executor != NULLPTR ? executor : GetCpuThreadPool();
    auto maybe_gen = std::move(get_gen)(used_executor);
    if (!maybe_gen.ok()) {
      return MakeErrorIterator<T>(maybe_gen.status());
    }
    return MakeGeneratorIterator(*maybe_gen);
  } else {
    return SerialExecutor::IterateGenerator(std::move(get_gen));
  }
}

/// \brief Potentially iterate an async generator serially (if use_threads is false)
///   using the default CPU thread pool