Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Threading.hh
Go to the documentation of this file.
1//
2// MIT License
3// Copyright (c) 2020 Jonathan R. Madsen
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED
12// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
13// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
16// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
17// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18//
19// ---------------------------------------------------------------
20// Tasking class header file
21//
22// Class Description:
23//
24// This file defines types and macros used to expose Tasking threading model.
25
26#pragma once
27
28#include "PTL/Globals.hh"
29#include "PTL/Types.hh"
30
31#include <chrono>
32#include <condition_variable>
33#include <future>
34#include <mutex>
35#include <thread>
36#include <vector>
37
38namespace PTL
39{
40// Macro to put current thread to sleep
41//
42#define THREADSLEEP(tick) std::this_thread::sleep_for(std::chrono::seconds(tick))
43
44// will be used in the future when migrating threading to task-based style
45template <typename Tp>
46using Future = std::future<Tp>;
47template <typename Tp>
48using SharedFuture = std::shared_future<Tp>;
49template <typename Tp>
50using Promise = std::promise<Tp>;
51
52//
53// NOTE ON Tasking SERIAL BUILDS AND MUTEX/UNIQUE_LOCK
54// ==================================================
55//
56// Mutex and RecursiveMutex are always C++11 std::mutex types
57// however, in serial mode, using MUTEXLOCK and MUTEXUNLOCK on these
58// types has no effect -- i.e. the mutexes are not actually locked or unlocked
59//
60// Additionally, when a Mutex or RecursiveMutex is used with AutoLock
61// and RecursiveAutoLock, respectively, these classes also suppressing
62// the locking and unlocking of the mutex. Regardless of the build type,
63// AutoLock and RecursiveAutoLock inherit from std::unique_lock<std::mutex>
64// and std::unique_lock<std::recursive_mutex>, respectively. This means
65// that in situations (such as is needed by the analysis category), the
66// AutoLock and RecursiveAutoLock can be passed to functions requesting
67// a std::unique_lock. Within these functions, since std::unique_lock
68// member functions are not virtual, they will not retain the dummy locking
69// and unlocking behavior
70// --> An example of this behavior can be found in AutoLock.hh
71//
72// Jonathan R. Madsen (February 21, 2018)
73//
74
75// global mutex types
76typedef std::mutex Mutex;
77typedef std::recursive_mutex RecursiveMutex;
78
79// mutex macros
80#define MUTEX_INITIALIZER \
81 {}
82#define MUTEXINIT(mutex) \
83 ; \
84 ;
85#define MUTEXDESTROY(mutex) \
86 ; \
87 ;
88
89// static functions: get_id(), sleep_for(...), sleep_until(...), yield(),
90namespace ThisThread
91{
92using namespace std::this_thread;
93}
94
95// will be used in the future when migrating threading to task-based style
96// and are currently used in unit tests
97template <typename Tp>
98using Promise = std::promise<Tp>;
99template <typename Tp>
100using Future = std::future<Tp>;
101template <typename Tp>
102using SharedFuture = std::shared_future<Tp>;
103
104// Some useful types
106typedef void* ThreadFunArgType;
107typedef int (*thread_lock)(Mutex*);
108typedef int (*thread_unlock)(Mutex*);
109
110// Helper function for getting a unique static mutex for a specific
111// class or type
112// Usage example:
113// a template class "Cache<T>" that required a static
114// mutex for specific to type T:
115// AutoLock l(TypeMutex<Cache<T>>());
116template <typename Tp>
117Mutex&
118TypeMutex(const unsigned int& _n = 0)
119{
120 static Mutex* _mutex = new Mutex();
121 if(_n == 0)
122 return *_mutex;
123
124 static std::vector<Mutex*> _mutexes;
125 if(_n > _mutexes.size())
126 _mutexes.resize(_n, nullptr);
127 if(!_mutexes[_n])
128 _mutexes[_n] = new Mutex();
129 return *(_mutexes[_n - 1]);
130}
131
132// Helper function for getting a unique static recursive_mutex for a
133// specific class or type
134// Usage example:
135// a template class "Cache<T>" that required a static
136// recursive_mutex for specific to type T:
137// RecursiveAutoLock l(TypeRecursiveMutex<Cache<T>>());
138template <typename Tp>
140TypeRecursiveMutex(const unsigned int& _n = 0)
141{
142 static RecursiveMutex* _mutex = new RecursiveMutex();
143 if(_n == 0)
144 return *(_mutex);
145
146 static std::vector<RecursiveMutex*> _mutexes;
147 if(_n > _mutexes.size())
148 _mutexes.resize(_n, nullptr);
149 if(!_mutexes[_n])
150 _mutexes[_n] = new RecursiveMutex();
151 return *(_mutexes[_n - 1]);
152}
153
154//======================================================================================//
155
156// global thread types
157typedef std::thread Thread;
158typedef std::thread::native_handle_type NativeThread;
159
160// mutex macros
161#define MUTEXLOCK(mutex) \
162 { \
163 (mutex)->lock(); \
164 }
165#define MUTEXUNLOCK(mutex) \
166 { \
167 (mutex)->unlock(); \
168 }
169
170// Macro to join thread
171#define THREADJOIN(worker) (worker).join()
172
173// std::thread::id does not cast to integer
174typedef std::thread::id Pid_t;
175
176// Instead of previous macro taking one argument, define function taking
177// unlimited arguments
178template <typename WorkerT, typename FuncT, typename... Args>
179void
180THREADCREATE(WorkerT*& worker, FuncT func, Args... args)
181{
182 *worker = Thread(func, std::forward<Args>(args)...);
183}
184
185// Conditions
186//
187// See MTRunManager for example on how to use these
188//
189typedef std::condition_variable Condition;
190#define CONDITION_INITIALIZER \
191 {}
192#define CONDITIONWAIT(cond, lock) (cond)->wait(*lock);
193#define CONDITIONWAITLAMBDA(cond, lock, lambda) (cond)->wait(*lock, lambda);
194#define CONDITIONNOTIFY(cond) (cond)->notify_one();
195#define CONDITIONBROADCAST(cond) (cond)->notify_all();
196//
197
198//======================================================================================//
199
200// Define here after Thread has been typedef
201typedef Thread::id ThreadId;
202
203//======================================================================================//
204
205namespace Threading
206{
207enum
208{
212 GENERICTHREAD_ID = -1000
214
215Pid_t
216GetPidId();
217unsigned
219int
221bool
223bool
225void
226SetThreadId(int aNewValue);
227bool
228SetPinAffinity(int idx, NativeThread& at);
229int
231int
233int
235} // namespace Threading
236
237} // namespace PTL
G4int(*)(G4Mutex *) thread_unlock
Definition: G4Threading.hh:115
G4int(*)(G4Mutex *) thread_lock
Definition: G4Threading.hh:113
Pid_t GetPidId()
Definition: Threading.cc:55
int WorkerThreadLeavesPool()
Definition: Threading.cc:112
unsigned GetNumberOfCores()
Definition: Threading.cc:64
bool IsMasterThread()
Definition: Threading.cc:87
int WorkerThreadJoinsPool()
Definition: Threading.cc:117
void SetThreadId(int aNewValue)
Definition: Threading.cc:72
bool IsWorkerThread()
Definition: Threading.cc:82
int GetNumberOfRunningWorkerThreads()
Definition: Threading.cc:122
int GetThreadId()
Definition: Threading.cc:77
bool SetPinAffinity(int idx, NativeThread &at)
Definition: Threading.cc:95
Definition: AutoLock.hh:254
std::thread::native_handle_type NativeThread
Definition: Threading.hh:158
std::recursive_mutex RecursiveMutex
Definition: Threading.hh:77
std::promise< Tp > Promise
Definition: Threading.hh:50
void * ThreadFunArgType
Definition: Threading.hh:106
void * ThreadFunReturnType
Definition: Threading.hh:105
std::future< Tp > Future
Definition: Threading.hh:46
std::condition_variable Condition
Definition: Threading.hh:189
std::mutex Mutex
Definition: Threading.hh:76
std::thread::id Pid_t
Definition: Threading.hh:174
RecursiveMutex & TypeRecursiveMutex(const unsigned int &_n=0)
Definition: Threading.hh:140
Mutex & TypeMutex(const unsigned int &_n=0)
Definition: Threading.hh:118
std::thread Thread
Definition: Threading.hh:157
void THREADCREATE(WorkerT *&worker, FuncT func, Args... args)
Definition: Threading.hh:180
std::shared_future< Tp > SharedFuture
Definition: Threading.hh:48
Thread::id ThreadId
Definition: Threading.hh:201