Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Threading.hh
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4Threading
27//
28// Description:
29//
30// This unit defines types and macros used to expose Geant4 threading model.
31
32// Author: Andrea Dotti, 15 February 2013 - First Implementation
33// Revision: Jonathan R. Madsen, 21 February 2018
34// --------------------------------------------------------------------
35#ifndef G4Threading_hh
36#define G4Threading_hh 1
37
38#include "G4Types.hh"
39#include "globals.hh"
40
41#include <chrono>
42#include <condition_variable>
43#include <future>
44#include <mutex>
45#include <thread>
46#include <vector>
47
48// Macro to put current thread to sleep
49//
50#define G4THREADSLEEP(tick) \
51 std::this_thread::sleep_for(std::chrono::seconds(tick))
52
53// Will be used in the future when migrating threading to task-based style
54template <typename _Tp>
55using G4Future = std::future<_Tp>;
56template <typename _Tp>
57using G4SharedFuture = std::shared_future<_Tp>;
58template <typename _Tp>
59using G4Promise = std::promise<_Tp>;
60
61// NOTE ON GEANT4 SERIAL BUILDS AND MUTEX/UNIQUE_LOCK
62// ==================================================
63//
64// G4Mutex and G4RecursiveMutex are always C++11 std::mutex types
65// however, in serial mode, using G4MUTEXLOCK and G4MUTEXUNLOCK on these
66// types has no effect -- i.e. the mutexes are not actually locked or unlocked
67//
68// Additionally, when a G4Mutex or G4RecursiveMutex is used with G4AutoLock
69// and G4RecursiveAutoLock, respectively, these classes also suppressing
70// the locking and unlocking of the mutex. Regardless of the build type,
71// G4AutoLock and G4RecursiveAutoLock inherit from std::unique_lock<std::mutex>
72// and std::unique_lock<std::recursive_mutex>, respectively. This means
73// that in situations (such as is needed by the analysis category), the
74// G4AutoLock and G4RecursiveAutoLock can be passed to functions requesting
75// a std::unique_lock. Within these functions, since std::unique_lock
76// member functions are not virtual, they will not retain the dummy locking
77// and unlocking behavior
78// --> An example of this behavior can be found in G4AutoLock.hh
79
80// Global mutex types
81using G4Mutex = std::mutex;
82using G4RecursiveMutex = std::recursive_mutex;
83
84// Mutex macros
85#define G4MUTEX_INITIALIZER \
86 {}
87#define G4MUTEXINIT(mutex) \
88 ; \
89 ;
90#define G4MUTEXDESTROY(mutex) \
91 ; \
92 ;
93
94// Static functions: get_id(), sleep_for(...), sleep_until(...), yield(),
95namespace G4ThisThread
96{
97 using namespace std::this_thread;
98}
99
100// Will be used in the future when migrating threading to task-based style
101// and are currently used in unit tests
102template <typename _Tp>
103using G4Promise = std::promise<_Tp>;
104template <typename _Tp>
105using G4Future = std::future<_Tp>;
106template <typename _Tp>
107using G4SharedFuture = std::shared_future<_Tp>;
108
109// Some useful types
111using G4ThreadFunArgType = void*;
113 G4int (*)(G4Mutex*); // typedef G4int (*thread_lock)(G4Mutex*);
115 G4int (*)(G4Mutex*); // typedef G4int (*thread_unlock)(G4Mutex*);
116
117// Helper function for getting a unique static mutex for a specific
118// class or type
119// Usage example:
120// a template class "G4Cache<T>" that required a static
121// mutex for specific to type T:
122// G4AutoLock l(G4TypeMutex<G4Cache<T>>());
123template <typename _Tp>
125{
126 static G4Mutex _mutex;
127 return _mutex;
128}
129
130// Helper function for getting a unique static recursive_mutex for a
131// specific class or type
132// Usage example:
133// a template class "G4Cache<T>" that required a static
134// recursive_mutex for specific to type T:
135// G4RecursiveAutoLock
136// l(G4TypeRecursiveMutex<G4Cache<T>>());
137template <typename _Tp>
139{
140 static G4RecursiveMutex _mutex;
141 return _mutex;
142}
143
144#if defined(G4MULTITHREADED)
145//==========================================
146// G4MULTITHREADED is ON - threading enabled
147//==========================================
148
149// global thread types
150using G4Thread = std::thread;
151using G4NativeThread = std::thread::native_handle_type;
152
153// mutex macros
154# define G4MUTEXLOCK(mutex) \
155 { \
156 (mutex)->lock(); \
157 }
158# define G4MUTEXUNLOCK(mutex) \
159 { \
160 (mutex)->unlock(); \
161 }
162
163// Macro to join thread
164# define G4THREADJOIN(worker) (worker).join()
165
166// std::thread::id does not cast to integer
167using G4Pid_t = std::thread::id;
168
169// Instead of previous macro taking one argument, define function taking
170// unlimited arguments
171template <typename _Worker, typename _Func, typename... _Args>
172void G4THREADCREATE(_Worker*& worker, _Func func, _Args... args)
173{
174 *worker = G4Thread(func, std::forward<_Args>(args)...);
175}
176
177// Conditions
178//
179// See G4MTRunManager for example on how to use these
180//
181using G4Condition = std::condition_variable;
182# define G4CONDITION_INITIALIZER \
183 {}
184# define G4CONDITIONWAIT(cond, lock) (cond)->wait(*lock);
185# define G4CONDITIONWAITLAMBDA(cond, lock, lambda) (cond)->wait(*lock, lambda);
186# define G4CONDITIONNOTIFY(cond) (cond)->notify_one();
187# define G4CONDITIONBROADCAST(cond) (cond)->notify_all();
188//
189// we don't define above globally so single-threaded code does not get
190// caught in condition with no other thread to wake it up
191//
192
193#else
194//==========================================
195// G4MULTITHREADED is OFF - Sequential build
196//==========================================
197
198// implement a dummy thread class that acts like a thread
200{
201 public:
203 using id = std::thread::id;
204
205 public:
206 // does nothing
208 // a std::thread-like constructor that execute upon construction
209 template <typename _Func, typename... _Args>
210 G4DummyThread(_Func func, _Args&&... _args)
211 {
212 func(std::forward<_Args>(_args)...);
213 }
214
215 public:
217 G4bool joinable() const { return true; }
218 id get_id() const noexcept { return std::this_thread::get_id(); }
220 void join() {}
221 void detach() {}
222
223 public:
224 static unsigned int hardware_concurrency() noexcept
225 {
226 return std::thread::hardware_concurrency();
227 }
228};
229
230// global thread types
233
234// mutex macros
235# define G4MUTEXLOCK(mutex) \
236 ; \
237 ;
238# define G4MUTEXUNLOCK(mutex) \
239 ; \
240 ;
241
242// Macro to join thread
243# define G4THREADJOIN(worker) \
244 ; \
245 ;
246
248
249// Instead of previous macro taking one argument, define function taking
250// unlimited arguments
251template <typename _Worker, typename _Func, typename... _Args>
252void G4THREADCREATE(_Worker*& worker, _Func func, _Args... args)
253{
254 *worker = G4Thread(func, std::forward<_Args>(args)...);
255}
256
258# define G4CONDITION_INITIALIZER 1
259# define G4CONDITIONWAIT(cond, mutex) G4ConsumeParameters(cond, mutex);
260# define G4CONDITIONWAITLAMBDA(cond, mutex, lambda) \
261 G4ConsumeParameters(cond, mutex, lambda);
262# define G4CONDITIONNOTIFY(cond) G4ConsumeParameters(cond);
263# define G4CONDITIONBROADCAST(cond) G4ConsumeParameters(cond);
264
265#endif // G4MULTITHREADING
266
267//============================================================================//
268
269// Define here after G4Thread has been typedef
271
272//============================================================================//
273
297
298#endif // G4Threading_hh
std::future< _Tp > G4Future
G4int(*)(G4Mutex *) thread_unlock
G4Thread::id G4ThreadId
G4int G4Pid_t
G4int G4Condition
void G4THREADCREATE(_Worker *&worker, _Func func, _Args... args)
G4RecursiveMutex & G4TypeRecursiveMutex()
std::recursive_mutex G4RecursiveMutex
std::shared_future< _Tp > G4SharedFuture
G4DummyThread G4Thread
G4DummyThread::native_handle_type G4NativeThread
std::promise< _Tp > G4Promise
void * G4ThreadFunReturnType
void * G4ThreadFunArgType
G4Mutex & G4TypeMutex()
std::mutex G4Mutex
G4int(*)(G4Mutex *) thread_lock
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4DummyThread(_Func func, _Args &&... _args)
G4bool joinable() const
static unsigned int hardware_concurrency() noexcept
G4int native_handle_type
void swap(G4DummyThread &)
id get_id() const noexcept
std::thread::id id
native_handle_type native_handle() const
G4int WorkerThreadJoinsPool()
G4bool G4SetPinAffinity(G4int idx, G4NativeThread &at)
G4int G4GetNumberOfCores()
G4int WorkerThreadLeavesPool()
G4bool IsWorkerThread()
G4bool IsMultithreadedApplication()
G4Pid_t G4GetPidId()
G4bool IsMasterThread()
G4int G4GetThreadId()
void SetMultithreadedApplication(G4bool value)
G4int GetNumberOfRunningWorkerThreads()
void G4SetThreadId(G4int aNewValue)