Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:01:50

0001 #ifndef FWCore_Concurrency_WaitingTask_h
0002 #define FWCore_Concurrency_WaitingTask_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Concurrency
0006 // Class  :     WaitingTask
0007 //
0008 /**\class WaitingTask WaitingTask.h FWCore/Concurrency/interface/WaitingTask.h
0009 
0010  Description: Task used by WaitingTaskList.
0011 
0012  Usage:
0013     Used as a callback to happen after a task has been completed. Includes the ability to hold an exception which has occurred while waiting.
0014 */
0015 //
0016 // Original Author:  Chris Jones
0017 //         Created:  Thu Feb 21 13:46:31 CST 2013
0018 // $Id$
0019 //
0020 
0021 // system include files
0022 #include <atomic>
0023 #include <exception>
0024 #include <memory>
0025 
0026 // user include files
0027 #include "FWCore/Concurrency/interface/TaskBase.h"
0028 
0029 // forward declarations
0030 
0031 namespace edm {
0032   class WaitingTaskList;
0033   class WaitingTaskHolder;
0034   class WaitingTaskWithArenaHolder;
0035 
0036   class WaitingTask : public TaskBase {
0037   public:
0038     friend class WaitingTaskList;
0039     friend class WaitingTaskHolder;
0040     friend class WaitingTaskWithArenaHolder;
0041 
0042     ///Constructor
0043     WaitingTask() : m_ptr{} {}
0044     ~WaitingTask() override{};
0045 
0046     // ---------- const member functions ---------------------------
0047 
0048     ///Returns exception thrown by dependent task
0049     /** If the value evalutes to true then the dependent task failed.
0050     */
0051     std::exception_ptr exceptionPtr() const {
0052       if (m_ptrSet == static_cast<unsigned char>(State::kSet)) {
0053         return m_ptr;
0054       }
0055       return std::exception_ptr{};
0056     }
0057 
0058   protected:
0059     std::exception_ptr const& uncheckedExceptionPtr() const { return m_ptr; }
0060 
0061   private:
0062     enum class State : unsigned char { kUnset = 0, kSetting = 1, kSet = 2 };
0063     ///Called if waited for task failed
0064     /**Allows transfer of the exception caused by the dependent task to be
0065      * moved to another thread.
0066      * This method should only be called by WaitingTaskList
0067      */
0068     void dependentTaskFailed(std::exception_ptr iPtr) {
0069       unsigned char isSet = static_cast<unsigned char>(State::kUnset);
0070       if (iPtr and m_ptrSet.compare_exchange_strong(isSet, static_cast<unsigned char>(State::kSetting))) {
0071         m_ptr = iPtr;
0072         m_ptrSet = static_cast<unsigned char>(State::kSet);
0073       }
0074     }
0075 
0076     std::exception_ptr m_ptr;
0077     std::atomic<unsigned char> m_ptrSet = static_cast<unsigned char>(State::kUnset);
0078   };
0079 
0080   template <typename F>
0081   class FunctorWaitingTask : public WaitingTask {
0082   public:
0083     explicit FunctorWaitingTask(F f) : func_(std::move(f)) {}
0084 
0085     void execute() final { func_(uncheckedExceptionPtr() ? &uncheckedExceptionPtr() : nullptr); };
0086 
0087   private:
0088     F func_;
0089   };
0090 
0091   template <typename F>
0092   FunctorWaitingTask<F>* make_waiting_task(F f) {
0093     return new FunctorWaitingTask<F>(std::move(f));
0094   }
0095 
0096 }  // namespace edm
0097 
0098 #endif