VMC Version 2.0
|
#include <chrono>
#include <iostream>
#include <mutex>
#include <system_error>
Go to the source code of this file.
Classes | |
class | TMCTemplateAutoLock< _Mutex_t > |
Macros | |
#define | TMCMULTITHREADED 1 |
TMCAutoLock.h. | |
#define | TMCMUTEX_INITIALIZER {} |
#define | TMCMUTEXLOCK(mutex) |
#define | TMCMUTEXUNLOCK(mutex) |
#define | _is_stand_mutex(_Tp) (std::is_same<_Tp, TMCMutex>::value) |
#define | _is_recur_mutex(_Tp) (std::is_same<_Tp, TMCRecursiveMutex>::value) |
#define | _is_other_mutex(_Tp) (!_is_stand_mutex(_Tp) && !_is_recur_mutex(_Tp)) |
Typedefs | |
using | TMCMutex = std::mutex |
using | TMCRecursiveMutex = std::recursive_mutex |
using | thread_lock = int(*)(TMCMutex *) |
using | thread_unlock = int(*)(TMCMutex *) |
using | TMCAutoLock = TMCTemplateAutoLock< TMCMutex > |
using | TMCRecursiveAutoLock = TMCTemplateAutoLock< TMCRecursiveMutex > |
template<typename _Tp > | |
using | TMCTAutoLock = TMCTemplateAutoLock< _Tp > |
#define TMCMULTITHREADED 1 |
Definition of the TMCTemplateAutoLock and TMCImpMutexAutoLock classes
void print_threading() { #ifdef TMCMULTITHREADED std::cout << "\nUsing TMCMULTITHREADED version..." << std::endl; #else std::cout << "\nUsing G4SERIAL version..." << std::endl; #endif }
============================================================================//
typedef std::unique_lock<std::mutex> unique_lock_t; functions for casting G4AutoLock to std::unique_lock to demonstrate that G4AutoLock is NOT polymorphic void as_unique_lock(unique_lock_t* lock) { lock->lock(); } void as_unique_unlock(unique_lock_t* lock) { lock->unlock(); }
============================================================================//
void run(const uint64_t& n) { sync the threads a bit std::this_thread::sleep_for(std::chrono::milliseconds(10));
get two mutexes to avoid deadlock when l32 actually locks G4AutoLock l32(G4TypeMutex<int32_t>(), std::defer_lock); G4AutoLock l64(G4TypeMutex<int64_t>(), std::defer_lock);
when serial: will not execute std::unique_lock::lock() because it overrides the member function l32.lock(); regardless of serial or MT: will execute std::unique_lock::lock() because std::unique_lock::lock() is not virtual as_unique_lock(&l64);
std::cout << "Running iteration " << n << "..." << std::endl; }
============================================================================// execute some work template <typename thread_type = std::thread>> void exec(uint64_t n) { get two mutexes to avoid deadlock when l32 actually locks G4AutoLock l32(G4TypeMutex<int32_t>(), std::defer_lock); G4AutoLock l64(G4TypeMutex<int64_t>(), std::defer_lock);
std::vector<thread_type*> threads(n, nullptr); for(uint64_t i = 0; i < n; ++i) { threads[i] = new thread_type(); (threads[i]) = std::move(thread_type(run, i)); }
when serial: will not execute std::unique_lock::lock() because it overrides the member function l32.lock(); regardless of serial or MT: will execute std::unique_lock::lock() because std::unique_lock::lock() is not virtual as_unique_lock(&l64);
std::cout << "Joining..." << std::endl;
when serial: will not execute std::unique_lock::unlock() because it overrides the member function l32.unlock(); regardless of serial or MT: will execute std::unique_lock::unlock() because std::unique_lock::unlock() is not virtual as_unique_unlock(&l64);
NOTE ABOUT UNLOCKS: in MT, commenting out either l32.unlock(); or as_unique_unlock(&l64); creates a deadlock; in serial, commenting out as_unique_unlock(&l64); creates a deadlock but commenting out l32.unlock(); does not
clean up and join for(uint64_t i = 0; i < n; ++i) { threads[i]->join(); delete threads[i]; } threads.clear(); }
============================================================================//
int main() { print_threading();
uint64_t n = 30; std::cout << "\nRunning with real threads...\n" << std::endl; exec<std::thread>(n); std::cout << "\nRunning with fake threads...\n" << std::endl; exec<G4DummyThread>(n);
}
Definition at line 298 of file TMCAutoLock.h.
#define TMCMUTEX_INITIALIZER {} |
Definition at line 319 of file TMCAutoLock.h.
#define TMCMUTEXLOCK | ( | mutex | ) |
Definition at line 324 of file TMCAutoLock.h.
#define TMCMUTEXUNLOCK | ( | mutex | ) |
Definition at line 328 of file TMCAutoLock.h.
#define _is_stand_mutex | ( | _Tp | ) | (std::is_same<_Tp, TMCMutex>::value) |
Definition at line 510 of file TMCAutoLock.h.
#define _is_recur_mutex | ( | _Tp | ) | (std::is_same<_Tp, TMCRecursiveMutex>::value) |
Definition at line 511 of file TMCAutoLock.h.
#define _is_other_mutex | ( | _Tp | ) | (!_is_stand_mutex(_Tp) && !_is_recur_mutex(_Tp)) |
Definition at line 512 of file TMCAutoLock.h.
using TMCMutex = std::mutex |
Definition at line 310 of file TMCAutoLock.h.
using TMCRecursiveMutex = std::recursive_mutex |
Definition at line 311 of file TMCAutoLock.h.
using thread_lock = int (*)(TMCMutex*) |
Definition at line 312 of file TMCAutoLock.h.
using thread_unlock = int (*)(TMCMutex*) |
Definition at line 314 of file TMCAutoLock.h.
using TMCAutoLock = TMCTemplateAutoLock<TMCMutex> |
Definition at line 650 of file TMCAutoLock.h.
Definition at line 651 of file TMCAutoLock.h.
using TMCTAutoLock = TMCTemplateAutoLock<_Tp> |
Definition at line 656 of file TMCAutoLock.h.