Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-07-19 00:58:35

0001 #ifndef FWCore_Concurrency_WaitingTaskHolder_h
0002 #define FWCore_Concurrency_WaitingTaskHolder_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     FWCore/Concurrency
0006 // Class  :     WaitingTaskHolder
0007 //
0008 /**\class WaitingTaskHolder WaitingTaskHolder.h "WaitingTaskHolder.h"
0009 
0010  Description: [one line class summary]
0011 
0012  Usage:
0013     <usage>
0014 
0015 */
0016 //
0017 // Original Author:  FWCore
0018 //         Created:  Fri, 18 Nov 2016 20:30:42 GMT
0019 //
0020 
0021 // system include files
0022 #include <cassert>
0023 #include "oneapi/tbb/task_group.h"
0024 
0025 // user include files
0026 #include "FWCore/Concurrency/interface/WaitingTask.h"
0027 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0028 
0029 // forward declarations
0030 
0031 namespace edm {
0032   class WaitingTaskHolder {
0033   public:
0034     friend class WaitingTaskList;
0035     friend class WaitingTaskWithArenaHolder;
0036 
0037     WaitingTaskHolder() : m_task(nullptr), m_group(nullptr) {}
0038 
0039     explicit WaitingTaskHolder(oneapi::tbb::task_group& iGroup, edm::WaitingTask* iTask)
0040         : m_task(iTask), m_group(&iGroup) {
0041       m_task->increment_ref_count();
0042     }
0043     ~WaitingTaskHolder() {
0044       if (m_task) {
0045         doneWaiting(std::exception_ptr{});
0046       }
0047     }
0048 
0049     WaitingTaskHolder(const WaitingTaskHolder& iHolder) : m_task(iHolder.m_task), m_group(iHolder.m_group) {
0050       m_task->increment_ref_count();
0051     }
0052 
0053     WaitingTaskHolder(WaitingTaskHolder&& iOther) : m_task(iOther.m_task), m_group(iOther.m_group) {
0054       iOther.m_task = nullptr;
0055     }
0056 
0057     WaitingTaskHolder& operator=(const WaitingTaskHolder& iRHS) {
0058       WaitingTaskHolder tmp(iRHS);
0059       std::swap(m_task, tmp.m_task);
0060       std::swap(m_group, tmp.m_group);
0061       return *this;
0062     }
0063 
0064     WaitingTaskHolder& operator=(WaitingTaskHolder&& iRHS) {
0065       WaitingTaskHolder tmp(std::move(iRHS));
0066       std::swap(m_task, tmp.m_task);
0067       std::swap(m_group, tmp.m_group);
0068       return *this;
0069     }
0070 
0071     // ---------- const member functions ---------------------
0072     bool taskHasFailed() const noexcept { return static_cast<bool>(m_task->exceptionPtr()); }
0073 
0074     bool hasTask() const noexcept { return m_task != nullptr; }
0075     /** since oneapi::tbb::task_group is thread safe, we can return it non-const from here since
0076         the object is not really part of the state of the holder
0077      */
0078     CMS_SA_ALLOW oneapi::tbb::task_group* group() const noexcept { return m_group; }
0079     // ---------- static member functions --------------------
0080 
0081     // ---------- member functions ---------------------------
0082 
0083     /** Use in the case where you need to inform the parent task of a
0084      failure before some other child task which may be run later reports
0085      a different, but related failure. You must later call doneWaiting
0086      in the same thread passing the same exceptoin.
0087      */
0088     void presetTaskAsFailed(std::exception_ptr iExcept) {
0089       if (iExcept) {
0090         m_task->dependentTaskFailed(iExcept);
0091       }
0092     }
0093 
0094     void doneWaiting(std::exception_ptr iExcept) {
0095       if (iExcept) {
0096         m_task->dependentTaskFailed(iExcept);
0097       }
0098       //task_group::run can run the task before we finish
0099       // doneWaiting and some other thread might
0100       // try to reuse this object. Resetting
0101       // before spawn avoids problems
0102       auto task = m_task;
0103       m_task = nullptr;
0104       if (0 == task->decrement_ref_count()) {
0105         m_group->run([task]() {
0106           TaskSentry s{task};
0107           task->execute();
0108         });
0109       }
0110     }
0111 
0112   private:
0113     WaitingTask* release_no_decrement() noexcept {
0114       auto t = m_task;
0115       m_task = nullptr;
0116       return t;
0117     }
0118     // ---------- member data --------------------------------
0119     WaitingTask* m_task;
0120     oneapi::tbb::task_group* m_group;
0121   };
0122 }  // namespace edm
0123 
0124 #endif