diff --git a/FWCore/Concurrency/interface/WaitingTask.h b/FWCore/Concurrency/interface/WaitingTask.h index d4c75cb707345..3f517bd2a0105 100644 --- a/FWCore/Concurrency/interface/WaitingTask.h +++ b/FWCore/Concurrency/interface/WaitingTask.h @@ -48,24 +48,33 @@ namespace edm { ///Returns exception thrown by dependent task /** If the value evalutes to true then the dependent task failed. */ - std::exception_ptr const& exceptionPtr() const { return m_ptr; } + std::exception_ptr exceptionPtr() const { + if (m_ptrSet == static_cast(State::kSet)) { + return m_ptr; + } + return std::exception_ptr{}; + } + + protected: + std::exception_ptr const& uncheckedExceptionPtr() const { return m_ptr; } private: + enum class State : unsigned char { kUnset = 0, kSetting = 1, kSet = 2 }; ///Called if waited for task failed /**Allows transfer of the exception caused by the dependent task to be * moved to another thread. * This method should only be called by WaitingTaskList */ void dependentTaskFailed(std::exception_ptr iPtr) { - bool isSet = false; - if (iPtr and m_ptrSet.compare_exchange_strong(isSet, true)) { + unsigned char isSet = static_cast(State::kUnset); + if (iPtr and m_ptrSet.compare_exchange_strong(isSet, static_cast(State::kSetting))) { m_ptr = iPtr; - //NOTE: the atomic counter in TaskBase will synchronize m_ptr + m_ptrSet = static_cast(State::kSet); } } std::exception_ptr m_ptr; - std::atomic m_ptrSet = false; + std::atomic m_ptrSet = static_cast(State::kUnset); }; template @@ -73,7 +82,7 @@ namespace edm { public: explicit FunctorWaitingTask(F f) : func_(std::move(f)) {} - void execute() final { func_(exceptionPtr() ? &exceptionPtr() : nullptr); }; + void execute() final { func_(uncheckedExceptionPtr() ? &uncheckedExceptionPtr() : nullptr); }; private: F func_; diff --git a/FWCore/Concurrency/interface/WaitingTaskHolder.h b/FWCore/Concurrency/interface/WaitingTaskHolder.h index 0ac8706c563f4..57fcc6f31898f 100644 --- a/FWCore/Concurrency/interface/WaitingTaskHolder.h +++ b/FWCore/Concurrency/interface/WaitingTaskHolder.h @@ -69,7 +69,7 @@ namespace edm { } // ---------- const member functions --------------------- - bool taskHasFailed() const noexcept { return m_task->exceptionPtr() != nullptr; } + bool taskHasFailed() const noexcept { return static_cast(m_task->exceptionPtr()); } bool hasTask() const noexcept { return m_task != nullptr; } /** since oneapi::tbb::task_group is thread safe, we can return it non-const from here since diff --git a/FWCore/Concurrency/src/WaitingTaskWithArenaHolder.cc b/FWCore/Concurrency/src/WaitingTaskWithArenaHolder.cc index 24b45ac5f1130..c6cf192800885 100644 --- a/FWCore/Concurrency/src/WaitingTaskWithArenaHolder.cc +++ b/FWCore/Concurrency/src/WaitingTaskWithArenaHolder.cc @@ -109,7 +109,7 @@ namespace edm { return holder; } - bool WaitingTaskWithArenaHolder::taskHasFailed() const noexcept { return m_task->exceptionPtr() != nullptr; } + bool WaitingTaskWithArenaHolder::taskHasFailed() const noexcept { return static_cast(m_task->exceptionPtr()); } bool WaitingTaskWithArenaHolder::hasTask() const noexcept { return m_task != nullptr; }