Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:30:14

0001 #ifndef SimG4Core_Application_ThreadHandoff_h
0002 #define SimG4Core_Application_ThreadHandoff_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     SimG4Core/Application
0006 // Class  :     ThreadHandoff
0007 //
0008 /**\class ThreadHandoff ThreadHandoff.h "SimG4Core/Application/interface/ThreadHandoff.h"
0009 
0010  Description: [one line class summary]
0011 
0012  Usage:
0013     <usage>
0014 
0015 */
0016 //
0017 // Original Author:  Christopher Jones
0018 //         Created:  Mon, 16 Aug 2021 13:51:53 GMT
0019 //
0020 
0021 // system include files
0022 #include <condition_variable>
0023 #include <cstring>  //strerror_r
0024 #include <exception>
0025 #include <mutex>
0026 #include <pthread.h>
0027 
0028 // user include files
0029 
0030 // forward declarations
0031 
0032 namespace omt {
0033   class ThreadHandoff {
0034   public:
0035     explicit ThreadHandoff(int stackSize);
0036     ~ThreadHandoff();
0037 
0038     ThreadHandoff(const ThreadHandoff&) = delete;                   // stop default
0039     const ThreadHandoff& operator=(const ThreadHandoff&) = delete;  // stop default
0040 
0041     template <typename F>
0042     void runAndWait(F&& iF) {
0043       Functor<F> f{std::move(iF)};
0044 
0045       std::unique_lock<std::mutex> lck(m_mutex);
0046       m_loopReady = false;
0047       m_toRun = &f;
0048 
0049       m_threadHandoff.notify_one();
0050 
0051       m_threadHandoff.wait(lck, [this]() { return m_loopReady; });
0052       auto e = f.exception();
0053       if (e) {
0054         std::rethrow_exception(e);
0055       }
0056     }
0057 
0058     void stopThread() {
0059       runAndWait([this]() { m_stopThread = true; });
0060     }
0061 
0062   private:
0063     class FunctorBase {
0064     public:
0065       virtual ~FunctorBase() {}
0066       virtual void execute() = 0;
0067     };
0068     template <typename F>
0069     class Functor : public FunctorBase {
0070     public:
0071       explicit Functor(F&& iF) : m_f(std::move(iF)) {}
0072       void execute() final {
0073         try {
0074           m_f();
0075         } catch (...) {
0076           m_except = std::current_exception();
0077         }
0078       }
0079       std::exception_ptr exception() { return m_except; }
0080 
0081     private:
0082       F m_f;
0083       std::exception_ptr m_except;
0084     };
0085 
0086     static void* threadLoop(void* iArgs);
0087 
0088     // ---------- member data --------------------------------
0089     pthread_t m_thread;
0090     std::mutex m_mutex;
0091     std::condition_variable m_threadHandoff;
0092 
0093     FunctorBase* m_toRun{nullptr};
0094     bool m_loopReady{false};
0095     bool m_stopThread{false};
0096   };
0097 }  // namespace omt
0098 #endif