OTPrimaryGeneratorAction 변경점
이제 OTPrimaryGeneratorAction은 이벤트 생성의 직접적인 의무를 모두 넘겨주었기 때문에 이벤트를 생성해야 하는 때에 OTMasterRunAction::GeneratePrimareis(G4Event *) 함수를 불러오는 역할만 남았다. 그렇기 때문에 기존 코드는 지우고 아래와 같이 적을 수 있다. OTPrimaryGeneratorAction(소스, 헤더)
void OTPrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent) { OTMasterRunAction *runAction = (OTMasterRunAction *) G4MTRunManager::GetMasterRunManager() -> GetUserRunAction(); runAction -> GeneratePrimaries(anEvent); }
그런데 여기서 주의할점이 있다. 앞서 스레드 안정성에 대해서 이야기를 하고 해결하지 않았지만 그 부분을 여기서 해결하도록 한다. 문제를 확하게 적자면, 이벤트 파일을 읽는 작업은 동시에 두 스레드가 요청하였을 때 충돌이 일어나면 프로그램이 멈추거나 멈추지 않더라도 결과를 믿을 수 없게 된다. 따라서 이 작업은 한번에 한 스레드만 허용하도록 해야 한다. 이런 문제는 mutex로 해결할 수 있다.
Mutex
Mutex란 Mutual Exclusive의 약자로, 번역하면 상호 배제라는 뜻으로 특정 역역에서 한번에 하나의 스레드만 진행을 허용하도록 하는 기술이다. 바로 OTPrimaryGeneratorAction에서 필요한 기능이다. Geant4에서도 자체적으로 이 기능을 지원하는데 바로 아래과 같이 적으면 된다.
... #include "G4AutoLock.hh" namespace { G4Mutex aMutex = G4MUTEX_INITIALIZER; } ... void OTPrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent) { G4AutoLock lock(&aMutex); OTMasterRunAction *runAction = (OTMasterRunAction *) G4MTRunManager::GetMasterRunManager() -> GetUserRunAction(); runAction -> GeneratePrimaries(anEvent); }
기존의 코드에서 헤더 "G4AutoLck.hh"와 바로 아래에
와 같이 적는다. 그리고 스레드가 한번에 하나만 허용되는 영역 앞에
와 같이 적으면 해당 영역은 한번에 한 스레드만 통과할 수 있다. 예를 들어 1번 스레드가 이 영역을 통과하려 할 때 이미 0번 스레드가 사용중이라면 1번 스레드는 0번 스레드가 영역을 빠져나갈 때 까지 기다려야 한다.