From fd7c78bbfb4276a93d9ee2d33ee9c0f33c8f6dd4 Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Sun, 15 Mar 2026 12:19:43 +0100 Subject: [PATCH] COMP: Let `Future.get()` calls in PoolMultiThreader always return void `Future` was declared as `std::future`, which is platform specific, and caused warnings on some platforms, as reported by Hans Johnson at https://github.com/InsightSoftwareConsortium/ITK/pull/5945 : itkPoolMultiThreader.cxx:148:55: warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result] exceptionHandler.TryAndCatch([this, threadLoop] { m_ThreadInfoArray[threadLoop].Future.get(); }); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Addressed by replacing the public `ThreadPoolInfoStruct` with a private `InternalWorkUnitInfo` struct, which has its `Future` declared as `std::future`. --- Modules/Core/Common/include/itkPoolMultiThreader.h | 13 +++++++++++-- Modules/Core/Common/src/itkPoolMultiThreader.cxx | 12 ++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Modules/Core/Common/include/itkPoolMultiThreader.h b/Modules/Core/Common/include/itkPoolMultiThreader.h index 45852a08714..bea05a6641c 100644 --- a/Modules/Core/Common/include/itkPoolMultiThreader.h +++ b/Modules/Core/Common/include/itkPoolMultiThreader.h @@ -95,10 +95,14 @@ class ITKCommon_EXPORT PoolMultiThreader : public MultiThreaderBase void SetMaximumNumberOfThreads(ThreadIdType numberOfThreads) override; - struct ThreadPoolInfoStruct : WorkUnitInfo +#ifndef ITK_FUTURE_LEGACY_REMOVE + struct ITK_FUTURE_DEPRECATED( + "PoolMultiThreader now uses a slightly different private `InternalWorkUnitInfo` struct instead!") + ThreadPoolInfoStruct : WorkUnitInfo { std::future Future; }; +#endif protected: PoolMultiThreader(); @@ -107,13 +111,18 @@ class ITKCommon_EXPORT PoolMultiThreader : public MultiThreaderBase PrintSelf(std::ostream & os, Indent indent) const override; private: + struct InternalWorkUnitInfo : WorkUnitInfo + { + std::future Future; + }; + // Thread pool instance and factory ThreadPool::Pointer m_ThreadPool{}; /** An array of work unit information containing a work unit id * (0, 1, 2, .. ITK_MAX_THREADS-1), work unit count, and a pointer * to void so that user data can be passed to each thread. */ - ThreadPoolInfoStruct m_ThreadInfoArray[ITK_MAX_THREADS]{}; + InternalWorkUnitInfo m_ThreadInfoArray[ITK_MAX_THREADS]{}; /** Friends of Multithreader. * ProcessObject is a friend so that it can call PrintSelf() on its diff --git a/Modules/Core/Common/src/itkPoolMultiThreader.cxx b/Modules/Core/Common/src/itkPoolMultiThreader.cxx index ae4df4c031f..03b06949c0a 100644 --- a/Modules/Core/Common/src/itkPoolMultiThreader.cxx +++ b/Modules/Core/Common/src/itkPoolMultiThreader.cxx @@ -132,7 +132,8 @@ PoolMultiThreader::SingleMethodExecute() { m_ThreadInfoArray[threadLoop].UserData = m_SingleData; m_ThreadInfoArray[threadLoop].NumberOfWorkUnits = m_NumberOfWorkUnits; - m_ThreadInfoArray[threadLoop].Future = m_ThreadPool->AddWork(m_SingleMethod, &m_ThreadInfoArray[threadLoop]); + m_ThreadInfoArray[threadLoop].Future = m_ThreadPool->AddWork( + [method = m_SingleMethod, threadInfo = &m_ThreadInfoArray[threadLoop]] { method(threadInfo); }); } // Now, the parent thread calls this->SingleMethod() itself @@ -175,8 +176,6 @@ PoolMultiThreader::ParallelizeArray(SizeValueType firstIndex, { aFunc(ii); } - // make this lambda have the same signature as m_SingleMethod - return ITK_THREAD_RETURN_DEFAULT_VALUE; }; SizeValueType workUnit = 1; @@ -265,11 +264,8 @@ PoolMultiThreader::ParallelizeImageRegion(unsigned int dimension, total = splitter->GetSplit(i, splitCount, iRegion); if (i < total) { - m_ThreadInfoArray[i].Future = m_ThreadPool->AddWork([funcP, iRegion]() { - funcP(&iRegion.GetIndex()[0], &iRegion.GetSize()[0]); - // make this lambda have the same signature as m_SingleMethod - return ITK_THREAD_RETURN_DEFAULT_VALUE; - }); + m_ThreadInfoArray[i].Future = + m_ThreadPool->AddWork([funcP, iRegion]() { funcP(&iRegion.GetIndex()[0], &iRegion.GetSize()[0]); }); } else {