Also, some thoughts about this function:
- It should accept more types, not only a vector of callables. We don't know what the caller is using std::array/std::vector/std::list (or any other container with a range).
- It should reject L-values. The caller must std::move the container so they are not copying it.
A patch that allows both points:
diff --git a/src/util/threadpool.h b/src/util/threadpool.h
--- a/src/util/threadpool.h
+++ b/src/util/threadpool.h
@@ -164,7 +164,10 @@
* uncaught exceptions, as they would otherwise be silently discarded.
*/
template <class F>
- [[nodiscard]] util::Expected<std::future<std::invoke_result_t<F>>, SubmitError> Submit(F&& fn) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+ using Future = std::future<std::invoke_result_t<F>>;
+
+ template <class F>
+ [[nodiscard]] util::Expected<Future<F>, SubmitError> Submit(F&& fn) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{
std::packaged_task<std::invoke_result_t<F>()> task{std::forward<F>(fn)};
auto future{task.get_future()};
@@ -200,11 +203,13 @@
* [@warning](/bitcoin-bitcoin/contributor/warning/) Ignoring the returned futures requires guarding tasks against
* uncaught exceptions, as they would otherwise be silently discarded.
*/
- template <class F>
- [[nodiscard]] util::Expected<std::vector<std::future<std::invoke_result_t<F>>>, SubmitError> SubmitMany(std::vector<F>&& fns) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
+ template <class F> using RangeValue = Future<std::ranges::range_value_t<F>>;
+
+ template <std::ranges::sized_range R>
+ requires (!std::is_lvalue_reference_v<R>) // Reject l-values; caller must explicitly std::move the range
+ [[nodiscard]] util::Expected<std::vector<RangeValue<R>>, SubmitError> SubmitMany(R&& fns) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{
- using Result = std::invoke_result_t<F&>;
- std::vector<std::future<Result>> futures;
+ std::vector<RangeValue<R>> futures;
futures.reserve(fns.size());
{
It would also be nice to expand submit_many_tasks_complete_successfully to use a different container, just to exercise the change. Could use std::array or std::list.