-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
ThreadHandoff.h
98 lines (80 loc) · 2.19 KB
/
ThreadHandoff.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef SimG4Core_Application_ThreadHandoff_h
#define SimG4Core_Application_ThreadHandoff_h
// -*- C++ -*-
//
// Package: SimG4Core/Application
// Class : ThreadHandoff
//
/**\class ThreadHandoff ThreadHandoff.h "SimG4Core/Application/interface/ThreadHandoff.h"
Description: [one line class summary]
Usage:
<usage>
*/
//
// Original Author: Christopher Jones
// Created: Mon, 16 Aug 2021 13:51:53 GMT
//
// system include files
#include <condition_variable>
#include <cstring> //strerror_r
#include <exception>
#include <mutex>
#include <pthread.h>
// user include files
// forward declarations
namespace omt {
class ThreadHandoff {
public:
explicit ThreadHandoff(int stackSize);
~ThreadHandoff();
ThreadHandoff(const ThreadHandoff&) = delete; // stop default
const ThreadHandoff& operator=(const ThreadHandoff&) = delete; // stop default
template <typename F>
void runAndWait(F&& iF) {
Functor<F> f{std::move(iF)};
std::unique_lock<std::mutex> lck(m_mutex);
m_loopReady = false;
m_toRun = &f;
m_threadHandoff.notify_one();
m_threadHandoff.wait(lck, [this]() { return m_loopReady; });
auto e = f.exception();
if (e) {
std::rethrow_exception(e);
}
}
void stopThread() {
runAndWait([this]() { m_stopThread = true; });
}
private:
class FunctorBase {
public:
virtual ~FunctorBase() {}
virtual void execute() = 0;
};
template <typename F>
class Functor : public FunctorBase {
public:
explicit Functor(F&& iF) : m_f(std::move(iF)) {}
void execute() final {
try {
m_f();
} catch (...) {
m_except = std::current_exception();
}
}
std::exception_ptr exception() { return m_except; }
private:
F m_f;
std::exception_ptr m_except;
};
static void* threadLoop(void* iArgs);
// ---------- member data --------------------------------
pthread_t m_thread;
std::mutex m_mutex;
std::condition_variable m_threadHandoff;
FunctorBase* m_toRun{nullptr};
bool m_loopReady{false};
bool m_stopThread{false};
};
} // namespace omt
#endif