Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/Geant4/G4Threading.hh was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // G4Threading
0027 //
0028 // Description:
0029 //
0030 // This unit defines types and macros used to expose Geant4 threading model.
0031 
0032 // Author: Andrea Dotti, 15 February 2013 - First Implementation
0033 // Revision: Jonathan R. Madsen, 21 February 2018
0034 // --------------------------------------------------------------------
0035 #ifndef G4Threading_hh
0036 #define G4Threading_hh 1
0037 
0038 #include "G4Types.hh"
0039 #include "globals.hh"
0040 
0041 #include <chrono>
0042 #include <condition_variable>
0043 #include <future>
0044 #include <mutex>
0045 #include <thread>
0046 #include <vector>
0047 
0048 // Macro to put current thread to sleep
0049 //
0050 #define G4THREADSLEEP(tick)                                                    \
0051   std::this_thread::sleep_for(std::chrono::seconds(tick))
0052 
0053 // Will be used in the future when migrating threading to task-based style
0054 template <typename _Tp>
0055 using G4Future = std::future<_Tp>;
0056 template <typename _Tp>
0057 using G4SharedFuture = std::shared_future<_Tp>;
0058 template <typename _Tp>
0059 using G4Promise = std::promise<_Tp>;
0060 
0061 //          NOTE ON GEANT4 SERIAL BUILDS AND MUTEX/UNIQUE_LOCK
0062 //          ==================================================
0063 //
0064 // G4Mutex and G4RecursiveMutex are always C++11 std::mutex types
0065 // however, in serial mode, using G4MUTEXLOCK and G4MUTEXUNLOCK on these
0066 // types has no effect -- i.e. the mutexes are not actually locked or unlocked
0067 //
0068 // Additionally, when a G4Mutex or G4RecursiveMutex is used with G4AutoLock
0069 // and G4RecursiveAutoLock, respectively, these classes also suppressing
0070 // the locking and unlocking of the mutex. Regardless of the build type,
0071 // G4AutoLock and G4RecursiveAutoLock inherit from std::unique_lock<std::mutex>
0072 // and std::unique_lock<std::recursive_mutex>, respectively. This means
0073 // that in situations (such as is needed by the analysis category), the
0074 // G4AutoLock and G4RecursiveAutoLock can be passed to functions requesting
0075 // a std::unique_lock. Within these functions, since std::unique_lock
0076 // member functions are not virtual, they will not retain the dummy locking
0077 // and unlocking behavior
0078 // --> An example of this behavior can be found in G4AutoLock.hh
0079 
0080 // Global mutex types
0081 using G4Mutex          = std::mutex;
0082 using G4RecursiveMutex = std::recursive_mutex;
0083 
0084 // Mutex macros
0085 #define G4MUTEX_INITIALIZER                                                    \
0086   {}
0087 #define G4MUTEXINIT(mutex)                                                     \
0088   ;                                                                            \
0089   ;
0090 #define G4MUTEXDESTROY(mutex)                                                  \
0091   ;                                                                            \
0092   ;
0093 
0094 // Static functions: get_id(), sleep_for(...), sleep_until(...), yield(),
0095 namespace G4ThisThread
0096 {
0097   using namespace std::this_thread;
0098 }
0099 
0100 // Will be used in the future when migrating threading to task-based style
0101 // and are currently used in unit tests
0102 template <typename _Tp>
0103 using G4Promise = std::promise<_Tp>;
0104 template <typename _Tp>
0105 using G4Future = std::future<_Tp>;
0106 template <typename _Tp>
0107 using G4SharedFuture = std::shared_future<_Tp>;
0108 
0109 // Some useful types
0110 using G4ThreadFunReturnType = void*;
0111 using G4ThreadFunArgType    = void*;
0112 using thread_lock =
0113   G4int (*)(G4Mutex*);  // typedef G4int (*thread_lock)(G4Mutex*);
0114 using thread_unlock =
0115   G4int (*)(G4Mutex*);  // typedef G4int (*thread_unlock)(G4Mutex*);
0116 
0117 // Helper function for getting a unique static mutex for a specific
0118 // class or type
0119 // Usage example:
0120 //   a template class "G4Cache<T>" that required a static
0121 //   mutex for specific to type T:
0122 //      G4AutoLock l(G4TypeMutex<G4Cache<T>>());
0123 template <typename _Tp>
0124 G4Mutex& G4TypeMutex()
0125 {
0126   static G4Mutex _mutex;
0127   return _mutex;
0128 }
0129 
0130 // Helper function for getting a unique static recursive_mutex for a
0131 // specific class or type
0132 // Usage example:
0133 //                a template class "G4Cache<T>" that required a static
0134 //                recursive_mutex for specific to type T:
0135 //                        G4RecursiveAutoLock
0136 //                        l(G4TypeRecursiveMutex<G4Cache<T>>());
0137 template <typename _Tp>
0138 G4RecursiveMutex& G4TypeRecursiveMutex()
0139 {
0140   static G4RecursiveMutex _mutex;
0141   return _mutex;
0142 }
0143 
0144 #if defined(G4MULTITHREADED)
0145 //==========================================
0146 // G4MULTITHREADED is ON - threading enabled
0147 //==========================================
0148 
0149 // global thread types
0150 using G4Thread       = std::thread;
0151 using G4NativeThread = std::thread::native_handle_type;
0152 
0153 // mutex macros
0154 #  define G4MUTEXLOCK(mutex)                                                   \
0155     {                                                                          \
0156       (mutex)->lock();                                                         \
0157     }
0158 #  define G4MUTEXUNLOCK(mutex)                                                 \
0159     {                                                                          \
0160       (mutex)->unlock();                                                       \
0161     }
0162 
0163 // Macro to join thread
0164 #  define G4THREADJOIN(worker) (worker).join()
0165 
0166 // std::thread::id does not cast to integer
0167 using G4Pid_t = std::thread::id;
0168 
0169 // Instead of previous macro taking one argument, define function taking
0170 // unlimited arguments
0171 template <typename _Worker, typename _Func, typename... _Args>
0172 void G4THREADCREATE(_Worker*& worker, _Func func, _Args... args)
0173 {
0174   *worker = G4Thread(func, std::forward<_Args>(args)...);
0175 }
0176 
0177 // Conditions
0178 //
0179 // See G4MTRunManager for example on how to use these
0180 //
0181 using G4Condition = std::condition_variable;
0182 #  define G4CONDITION_INITIALIZER                                              \
0183     {}
0184 #  define G4CONDITIONWAIT(cond, lock) (cond)->wait(*lock);
0185 #  define G4CONDITIONWAITLAMBDA(cond, lock, lambda) (cond)->wait(*lock, lambda);
0186 #  define G4CONDITIONNOTIFY(cond) (cond)->notify_one();
0187 #  define G4CONDITIONBROADCAST(cond) (cond)->notify_all();
0188 //
0189 // we don't define above globally so single-threaded code does not get
0190 // caught in condition with no other thread to wake it up
0191 //
0192 
0193 #else
0194 //==========================================
0195 // G4MULTITHREADED is OFF - Sequential build
0196 //==========================================
0197 
0198 // implement a dummy thread class that acts like a thread
0199 class G4DummyThread
0200 {
0201  public:
0202   using native_handle_type = G4int;
0203   using id                 = std::thread::id;
0204 
0205  public:
0206   // does nothing
0207   G4DummyThread() {}
0208   // a std::thread-like constructor that execute upon construction
0209   template <typename _Func, typename... _Args>
0210   G4DummyThread(_Func func, _Args&&... _args)
0211   {
0212     func(std::forward<_Args>(_args)...);
0213   }
0214 
0215  public:
0216   native_handle_type native_handle() const { return native_handle_type(); }
0217   G4bool joinable() const { return true; }
0218   id get_id() const noexcept { return std::this_thread::get_id(); }
0219   void swap(G4DummyThread&) {}
0220   void join() {}
0221   void detach() {}
0222 
0223  public:
0224   static unsigned int hardware_concurrency() noexcept
0225   {
0226     return std::thread::hardware_concurrency();
0227   }
0228 };
0229 
0230 // global thread types
0231 using G4Thread       = G4DummyThread;
0232 using G4NativeThread = G4DummyThread::native_handle_type;
0233 
0234 // mutex macros
0235 #  define G4MUTEXLOCK(mutex)                                                   \
0236     ;                                                                          \
0237     ;
0238 #  define G4MUTEXUNLOCK(mutex)                                                 \
0239     ;                                                                          \
0240     ;
0241 
0242 // Macro to join thread
0243 #  define G4THREADJOIN(worker)                                                 \
0244     ;                                                                          \
0245     ;
0246 
0247 using G4Pid_t = G4int;
0248 
0249 // Instead of previous macro taking one argument, define function taking
0250 // unlimited arguments
0251 template <typename _Worker, typename _Func, typename... _Args>
0252 void G4THREADCREATE(_Worker*& worker, _Func func, _Args... args)
0253 {
0254   *worker = G4Thread(func, std::forward<_Args>(args)...);
0255 }
0256 
0257 using G4Condition = G4int;
0258 #  define G4CONDITION_INITIALIZER 1
0259 #  define G4CONDITIONWAIT(cond, mutex) G4ConsumeParameters(cond, mutex);
0260 #  define G4CONDITIONWAITLAMBDA(cond, mutex, lambda)                           \
0261     G4ConsumeParameters(cond, mutex, lambda);
0262 #  define G4CONDITIONNOTIFY(cond) G4ConsumeParameters(cond);
0263 #  define G4CONDITIONBROADCAST(cond) G4ConsumeParameters(cond);
0264 
0265 #endif  // G4MULTITHREADING
0266 
0267 //============================================================================//
0268 
0269 // Define here after G4Thread has been typedef
0270 using G4ThreadId = G4Thread::id;
0271 
0272 //============================================================================//
0273 
0274 namespace G4Threading
0275 {
0276   enum
0277   {
0278     SEQUENTIAL_ID    = -2,
0279     MASTER_ID        = -1,
0280     WORKER_ID        = 0,
0281     GENERICTHREAD_ID = -1000
0282   };
0283 
0284   G4Pid_t G4GetPidId();
0285   G4int G4GetNumberOfCores();
0286   G4int G4GetThreadId();
0287   G4bool IsWorkerThread();
0288   G4bool IsMasterThread();
0289   void G4SetThreadId(G4int aNewValue);
0290   G4bool G4SetPinAffinity(G4int idx, G4NativeThread& at);
0291   void SetMultithreadedApplication(G4bool value);
0292   G4bool IsMultithreadedApplication();
0293   G4int WorkerThreadLeavesPool();
0294   G4int WorkerThreadJoinsPool();
0295   G4int GetNumberOfRunningWorkerThreads();
0296 }  // namespace G4Threading
0297 
0298 #endif  // G4Threading_hh