File indexing completed on 2024-04-06 12:30:14
0001 #ifndef SimG4Core_Application_ThreadHandoff_h
0002 #define SimG4Core_Application_ThreadHandoff_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <condition_variable>
0023 #include <cstring> //strerror_r
0024 #include <exception>
0025 #include <mutex>
0026 #include <pthread.h>
0027
0028
0029
0030
0031
0032 namespace omt {
0033 class ThreadHandoff {
0034 public:
0035 explicit ThreadHandoff(int stackSize);
0036 ~ThreadHandoff();
0037
0038 ThreadHandoff(const ThreadHandoff&) = delete;
0039 const ThreadHandoff& operator=(const ThreadHandoff&) = delete;
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
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 }
0098 #endif