From 7da55c7dd539ac12dee8b0a17c7330c440813d78 Mon Sep 17 00:00:00 2001
From: adrien-matta <a.matta@surrey.ac.uk>
Date: Wed, 8 Apr 2015 19:11:42 +0100
Subject: [PATCH] * Establishing a multithreded environment for the detector
 manager

---
 NPAnalysis/newMUGAST/Analysis.cxx      |   1 -
 NPLib/Core/NPDetectorManager.cxx       | 102 ++++++++++++++++++++-----
 NPLib/Core/NPDetectorManager.h         |  40 +++++++++-
 NPLib/Core/NPVDetector.cxx             |  12 +--
 NPLib/GASPARD/GaspardTracker.cxx       |  26 +++----
 NPLib/GASPARD/TGaspardTrackerData.h    |  23 ++++--
 NPLib/MUST2/TMust2Physics.cxx          |   1 -
 NPLib/Utility/npanalysis.cxx           |  21 +++--
 NPSimulation/GASPARD/GaspardScorers.cc |   1 +
 9 files changed, 160 insertions(+), 67 deletions(-)

diff --git a/NPAnalysis/newMUGAST/Analysis.cxx b/NPAnalysis/newMUGAST/Analysis.cxx
index 1333b471e..65d54642a 100644
--- a/NPAnalysis/newMUGAST/Analysis.cxx
+++ b/NPAnalysis/newMUGAST/Analysis.cxx
@@ -77,7 +77,6 @@ void Analysis::TreatEvent(){
   myReaction->SetBeamEnergy(BeamEnergy);
   //////////////////////////// LOOP on MUST2 //////////////////
   for(unsigned int countMust2 = 0 ; countMust2 < M2->Si_E.size() ; countMust2++){
-    cout << "MUST2 " << endl;
     /************************************************/
     //Part 0 : Get the usefull Data
     // MUST2
diff --git a/NPLib/Core/NPDetectorManager.cxx b/NPLib/Core/NPDetectorManager.cxx
index b58360f5a..28392d707 100644
--- a/NPLib/Core/NPDetectorManager.cxx
+++ b/NPLib/Core/NPDetectorManager.cxx
@@ -36,11 +36,27 @@
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //   Default Constructor
 DetectorManager::DetectorManager(){
+  m_BuildPhysicalPtr = &NPA::VDetector::BuildPhysicalEvent;
+  m_ClearEventPhysicsPtr =  &NPA::VDetector::ClearEventPhysics;
+  m_ClearEventDataPtr = &NPA::VDetector::ClearEventData ;
+  m_FillSpectra = NULL; 
+  m_CheckSpectra = NULL;   
+  
+  if(NPOptionManager::getInstance()->GetGenerateHistoOption()){
+    m_FillSpectra =  &NPA::VDetector::FillSpectra ;
+    if(NPOptionManager::getInstance()->GetCheckHistoOption())
+      m_CheckSpectra = &NPA::VDetector::CheckSpectra ;
+  }
 }
 
+
 /////////////////////////////////////////////////////////////////////////////////////////////////   
 //   Default Desstructor
 DetectorManager::~DetectorManager(){
+#if __cplusplus > 199711L
+  StopThread();
+#endif
+
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
@@ -71,8 +87,6 @@ void DetectorManager::ReadConfigurationFile(string Path)   {
     cout << "Configuration file " << Path << " loading " << endl;
   }
 
-
-
   while (!ConfigFile.eof()) {
     // Pick-up next line
     getline(ConfigFile, LineBuffer);
@@ -114,22 +128,34 @@ void DetectorManager::ReadConfigurationFile(string Path)   {
 
   // The calibration Manager got all the parameter added, so it can load them from the calibration file
   CalibrationManager::getInstance()->LoadParameterFromFile();
-
+#if __cplusplus > 199711L
+//  thread(&DetectorManager::InitThreadPool,this).detach();
+InitThreadPool();
+#endif
+  
   return;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////   
 void DetectorManager::BuildPhysicalEvent(){
-  ClearEventPhysics();
+#if __cplusplus > 199711L
+ // add new jobs
+  map<string,VDetector*>::iterator it;
+  unsigned int i = 0;
+  for (it = m_Detector.begin(); it != m_Detector.end(); ++it) {
+    m_Ready[i++]=true;
+  }
+
+  // Wait for all job to be done
+  while(!IsDone()){} 
+
+#else 
   map<string,VDetector*>::iterator it;
    for (it = m_Detector.begin(); it != m_Detector.end(); ++it) {
-    it->second->BuildPhysicalEvent();
-    if(NPOptionManager::getInstance()->GetGenerateHistoOption()){
-      it->second->FillSpectra();
-      if(NPOptionManager::getInstance()->GetCheckHistoOption())
-        it->second->CheckSpectra();
-    }  
+      (it->second->*m_ClearEventPhysicsPtr)();
+      (it->second->*m_BuildPhysicalPtr)();
   }
+#endif
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
@@ -198,25 +224,20 @@ VDetector* DetectorManager::GetDetector(string name){
 /////////////////////////////////////////////////////////////////////////////////////////////////
 void DetectorManager::ClearEventPhysics(){
   map<string,VDetector*>::iterator it;
-
   for (it = m_Detector.begin(); it != m_Detector.end(); ++it) 
-    it->second->ClearEventPhysics();
-  
+    (it->second->*m_ClearEventPhysicsPtr)();
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 void DetectorManager::ClearEventData(){
   map<string,VDetector*>::iterator it;
-
   for (it = m_Detector.begin(); it != m_Detector.end(); ++it)
-    it->second->ClearEventData();
-  
+    (it->second->*m_ClearEventDataPtr)();
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////   
 void DetectorManager::InitSpectra(){
   map<string,VDetector*>::iterator it;
-
   for (it = m_Detector.begin(); it != m_Detector.end(); ++it) 
     it->second->InitSpectra();
 }
@@ -224,16 +245,13 @@ void DetectorManager::InitSpectra(){
 /////////////////////////////////////////////////////////////////////////////////////////////////   
 void DetectorManager::WriteSpectra(){
   map<string,VDetector*>::iterator it;
-
   for (it = m_Detector.begin(); it != m_Detector.end(); ++it) 
     it->second->WriteSpectra();
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////   
-vector< map< vector<string>, TH1* > > DetectorManager::GetSpectra()
-{
+vector< map< vector<string>, TH1* > > DetectorManager::GetSpectra(){
    vector< map< vector<string>, TH1* > > myVector;
-
    map<string,VDetector*>::iterator it;
    // loop on detectors
    for (it = m_Detector.begin(); it != m_Detector.end(); ++it) {
@@ -253,4 +271,46 @@ vector<string> DetectorManager::GetDetectorList(){
 
   return DetectorList;
 }
+#if __cplusplus > 199711L 
+////////////////////////////////////////////////////////////////////////////////
+void DetectorManager::InitThreadPool(){
+  StopThread();
+  m_ThreadPool.clear();
+  m_Ready.clear();
+  map<string,VDetector*>::iterator it;
+  unsigned int i = 0;
+  for (it = m_Detector.begin(); it != m_Detector.end(); ++it) { 
+    m_ThreadPool.push_back( thread( &DetectorManager::StartThread,this,it->second,i++) );
+    m_Ready.push_back(false);
+  }
+
+  m_stop = false;
+  for(auto& th: m_ThreadPool){
+    th.detach();
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void DetectorManager::StartThread(NPA::VDetector* det,unsigned int id){ 
+  while(!m_stop){
+    if(m_Ready[id]){
+      (det->*m_ClearEventPhysicsPtr)();
+      (det->*m_BuildPhysicalPtr)();
+      m_Ready[id]=false;
+    }
+  }
+}
+////////////////////////////////////////////////////////////////////////////////
+void DetectorManager::StopThread(){
+  m_stop=true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool DetectorManager::IsDone(){
+  for(vector<bool>::iterator i =  m_Ready.begin() ; i!=m_Ready.end() ; i++){
+    if((*i))
+      return false;
+  }
+  return true;
+}
+#endif
 
diff --git a/NPLib/Core/NPDetectorManager.h b/NPLib/Core/NPDetectorManager.h
index eafe418c4..ea7f92cbc 100644
--- a/NPLib/Core/NPDetectorManager.h
+++ b/NPLib/Core/NPDetectorManager.h
@@ -29,10 +29,21 @@
 //   STL
 #include <string>
 #include <map>
+#include <queue>
+#if __cplusplus > 199711L 
+#include<thread>
+#include<mutex>
+#endif
+
 using namespace std ;
 
 using namespace NPA ;
 
+// Anonymous namespace
+namespace{
+  typedef void(VDetector::*FuncPtr)(void);
+}
+
 // This class manage a map of virtual detector
 namespace NPA{
   class DetectorManager{
@@ -41,7 +52,6 @@ namespace NPA{
       ~DetectorManager();
 
     public:
-      // Read stream at Path and pick-up Token declaration of Detector
       void        ReadConfigurationFile(string Path);
       void        BuildPhysicalEvent();
       void        BuildSimplePhysicalEvent();
@@ -55,14 +65,32 @@ namespace NPA{
       void        WriteSpectra();
       vector< map< vector<string>, TH1* > > GetSpectra();  
       vector<string>                        GetDetectorList();
+
     private:   
       // The map containning all detectors
       // Using a Map one can access to any detector using its name
       map<string,VDetector*> m_Detector;
 
-      // Special treatment for the target for the moment
-      // If necessary we should change it to treat it as 
-      // a full "detector"
+    private: // Function pointer to accelerate the code execution
+      FuncPtr m_BuildPhysicalPtr;
+      FuncPtr m_ClearEventPhysicsPtr;
+      FuncPtr m_ClearEventDataPtr;
+      FuncPtr m_FillSpectra;
+      FuncPtr m_CheckSpectra;
+
+    #if __cplusplus > 199711L 
+    private: // Thread Pool defined if C++11 is available
+      vector<thread> m_ThreadPool;
+      vector<bool> m_Ready;
+      bool m_stop;
+    
+    public: // Init the Thread Pool
+      void StopThread();
+      void StartThread(NPA::VDetector*,unsigned int);
+      void InitThreadPool(); 
+      bool IsDone();
+    #endif
+
     private:
       double m_TargetThickness;
       double m_TargetAngle;
@@ -72,6 +100,10 @@ namespace NPA{
       double m_TargetY;
       double m_TargetZ;
 
+      // Special treatment for the target for the moment
+      // If necessary we should change it to treat it as 
+      // a full "detector"
+
     public:
       double GetTargetThickness()     {return m_TargetThickness;}
       string GetTargetMaterial()      {return m_TargetMaterial;}
diff --git a/NPLib/Core/NPVDetector.cxx b/NPLib/Core/NPVDetector.cxx
index ad6fbde27..8bfa0472e 100644
--- a/NPLib/Core/NPVDetector.cxx
+++ b/NPLib/Core/NPVDetector.cxx
@@ -22,19 +22,19 @@
  *   See MUST2 array for exemple of VDetector derived class                  *
  *                                                                           *
  *****************************************************************************/
- #include "NPVDetector.h"
-
+#include "NPVDetector.h"
+#include "NPOptionManager.h"
 using namespace NPA ;
 
 ClassImp(VDetector);
 
 // Constructor
-VDetector::VDetector()
-{
+VDetector::VDetector(){
 }
 
 
 // Destructor
-VDetector::~VDetector()
-{
+VDetector::~VDetector(){
 }
+
+
diff --git a/NPLib/GASPARD/GaspardTracker.cxx b/NPLib/GASPARD/GaspardTracker.cxx
index b3bd9a207..06886b98d 100644
--- a/NPLib/GASPARD/GaspardTracker.cxx
+++ b/NPLib/GASPARD/GaspardTracker.cxx
@@ -228,8 +228,7 @@ void GaspardTracker::InitializeRootInputRaw()
 
 
 
-void GaspardTracker::InitializeRootInputPhysics()
-{
+void GaspardTracker::InitializeRootInputPhysics(){
    TChain* inputChain = RootInput::getInstance()->GetChain();
    inputChain->SetBranchAddress("GASPARD" , &m_EventPhysics);
 }
@@ -237,8 +236,7 @@ void GaspardTracker::InitializeRootInputPhysics()
 
 
 // Create associated branches and associated private member DetectorPhysics address
-void GaspardTracker::InitializeRootOutput()    
-{
+void GaspardTracker::InitializeRootOutput()    {
    TTree* outputTree = RootOutput::getInstance()->GetTree();
    outputTree->Branch("GASPARD", "TGaspardTrackerPhysics", &m_EventPhysics);
 }
@@ -246,23 +244,19 @@ void GaspardTracker::InitializeRootOutput()
 
 
 // This method is called at each event read from the Input Tree. Aime is to build treat Raw dat in order to extract physical parameter. 
-void GaspardTracker::BuildPhysicalEvent()      
-{
-   if (m_EventData->GetGPDTrkFirstStageFrontEMult() > 0) {
-      for (UInt_t i = 0; i < m_EventData->GetGPDTrkFirstStageFrontEMult(); i++) {
-         UShort_t detecNbr = m_EventData->GetGPDTrkFirstStageFrontEDetectorNbr(i);
-         m_ModulesMap[detecNbr]->BuildPhysicalEvent();
-      }
-   }
+void GaspardTracker::BuildPhysicalEvent()      {
+  unsigned int mysize = m_EventData->GetGPDTrkFirstStageFrontEMult() ;
+      
+  for (unsigned int i = 0; i < mysize; i++) {
+        UShort_t detecNbr = m_EventData->GetGPDTrkFirstStageFrontEDetectorNbr(i);
+        m_ModulesMap[detecNbr]->BuildPhysicalEvent();
+  }
 }
 
-
-
 // Same as above, but only the simplest event and/or simple method are used (low multiplicity, faster algorythm but less efficient ...).
 // This method aimed to be used for analysis performed during experiment, when speed is requiered.
 // NB: This method can eventually be the same as BuildPhysicalEvent.
-void GaspardTracker::BuildSimplePhysicalEvent()   
-{
+void GaspardTracker::BuildSimplePhysicalEvent(){
    BuildPhysicalEvent();
 }
 
diff --git a/NPLib/GASPARD/TGaspardTrackerData.h b/NPLib/GASPARD/TGaspardTrackerData.h
index 5186cac05..cd29f3b4b 100644
--- a/NPLib/GASPARD/TGaspardTrackerData.h
+++ b/NPLib/GASPARD/TGaspardTrackerData.h
@@ -30,7 +30,6 @@
 
 #include <vector>
 #include "TObject.h"
-
 using namespace std ;
 
 class TGaspardTrackerData : public TObject
@@ -179,10 +178,13 @@ public:
    // DSSD
    // (Front, E)
    UShort_t GetGPDTrkFirstStageFrontEMult()               {
-      return fGPDTrk_FirstStage_FrontE_DetectorNbr.size();
+     if(fGPDTrk_FirstStage_FrontE_DetectorNbr.size()!= fGPDTrk_FirstStage_FrontE_StripNbr.size() || fGPDTrk_FirstStage_FrontE_DetectorNbr.size()!= fGPDTrk_FirstStage_FrontE_Energy.size())
+       return 0;
+     
+     return fGPDTrk_FirstStage_FrontE_DetectorNbr.size();
    }
    UShort_t GetGPDTrkFirstStageFrontEDetectorNbr(Int_t i) {
-      return fGPDTrk_FirstStage_FrontE_DetectorNbr.at(i);
+     return fGPDTrk_FirstStage_FrontE_DetectorNbr.at(i);
    }
    UShort_t GetGPDTrkFirstStageFrontEStripNbr(Int_t i)    {
       return fGPDTrk_FirstStage_FrontE_StripNbr.at(i);
@@ -192,7 +194,10 @@ public:
    }
    // (Front, T)
    UShort_t GetGPDTrkFirstStageFrontTMult()               {
-      return fGPDTrk_FirstStage_FrontT_DetectorNbr.size();
+     if(fGPDTrk_FirstStage_FrontT_DetectorNbr.size()!= fGPDTrk_FirstStage_FrontT_StripNbr.size() || fGPDTrk_FirstStage_FrontT_DetectorNbr.size()!= fGPDTrk_FirstStage_FrontT_Time.size())
+       return 0;
+ 
+     return fGPDTrk_FirstStage_FrontT_DetectorNbr.size();
    }
    UShort_t GetGPDTrkFirstStageFrontTDetectorNbr(Int_t i) {
       return fGPDTrk_FirstStage_FrontT_DetectorNbr.at(i);
@@ -205,7 +210,10 @@ public:
    }
    // (Back, E)
    UShort_t GetGPDTrkFirstStageBackEMult()               {
-      return fGPDTrk_FirstStage_BackE_DetectorNbr.size();
+    if(fGPDTrk_FirstStage_BackE_DetectorNbr.size()!= fGPDTrk_FirstStage_BackE_StripNbr.size() || fGPDTrk_FirstStage_BackE_DetectorNbr.size()!= fGPDTrk_FirstStage_BackE_Energy.size())
+       return 0;
+     
+     return fGPDTrk_FirstStage_BackE_DetectorNbr.size();
    }
    UShort_t GetGPDTrkFirstStageBackEDetectorNbr(Int_t i) {
       return fGPDTrk_FirstStage_BackE_DetectorNbr.at(i);
@@ -218,7 +226,10 @@ public:
    }
    // (Back, T)
    UShort_t GetGPDTrkFirstStageBackTMult()               {
-      return fGPDTrk_FirstStage_BackT_DetectorNbr.size();
+    if(fGPDTrk_FirstStage_BackT_DetectorNbr.size()!= fGPDTrk_FirstStage_BackT_StripNbr.size() || fGPDTrk_FirstStage_BackT_DetectorNbr.size()!= fGPDTrk_FirstStage_BackT_Time.size())
+       return 0;
+ 
+     return fGPDTrk_FirstStage_BackT_DetectorNbr.size();
    }
    UShort_t GetGPDTrkFirstStageBackTDetectorNbr(Int_t i) {
       return fGPDTrk_FirstStage_BackT_DetectorNbr.at(i);
diff --git a/NPLib/MUST2/TMust2Physics.cxx b/NPLib/MUST2/TMust2Physics.cxx
index 7b713aef1..16f29afe3 100644
--- a/NPLib/MUST2/TMust2Physics.cxx
+++ b/NPLib/MUST2/TMust2Physics.cxx
@@ -311,7 +311,6 @@ void TMust2Physics::BuildPhysicalEvent(){
 
     }
   }
-
   return;
 
 }
diff --git a/NPLib/Utility/npanalysis.cxx b/NPLib/Utility/npanalysis.cxx
index b56fe6fc2..9ba6ecd12 100644
--- a/NPLib/Utility/npanalysis.cxx
+++ b/NPLib/Utility/npanalysis.cxx
@@ -80,16 +80,13 @@ int main(int argc , char** argv){
 
   clock_t begin = clock();
   clock_t end = begin;
-  unsigned int treated = 0;
   unsigned int inter = 0;
-
+  unsigned int treated = 0;
   if(UserAnalysis==NULL){ 
     for (unsigned int i = 0 ; i < nentries; i++) { 
       ProgressDisplay(begin,end,treated,inter,nentries);
       // Get the raw Data
       Chain -> GetEntry(i);
-      // Clear previous Event
-      myDetector->ClearEventPhysics();
       // Build the current event
       myDetector->BuildPhysicalEvent();
       // Fill the tree
@@ -102,18 +99,17 @@ int main(int argc , char** argv){
       ProgressDisplay(begin,end,treated,inter,nentries);
       // Get the raw Data
       Chain -> GetEntry(i);
-      // Clear previous Event
-      myDetector->ClearEventPhysics();
       // Build the current event
       myDetector->BuildPhysicalEvent();
       // User Analysis
       UserAnalysis->TreatEvent();
-      // Fill the tree
+      // Fill the tree      
       tree->Fill();
     }
     UserAnalysis->End();
   }
 
+  myDetector->StopThread();
   ProgressDisplay(begin,end,treated,inter,nentries);
   RootOutput::getInstance()->Destroy();
   return 0;
@@ -123,20 +119,21 @@ int main(int argc , char** argv){
 void ProgressDisplay(clock_t& begin, clock_t& end, unsigned int& treated,unsigned int& inter,int& total){
   end = clock();
   if((end-begin)>CLOCKS_PER_SEC||treated>=total ){
-    long double elapsed =(long double) (end-begin)/CLOCKS_PER_SEC;
+  long double elapsed =(long double) (end-begin)/CLOCKS_PER_SEC;
     double event_rate = inter/elapsed;
     double percent = 100*treated/total;
     double remain = (total-treated)/event_rate;
 
     char* timer;
     if(remain>60)
-      asprintf(&timer,"%.dmin",(int)(remain/60));
+      asprintf(&timer,"%.dmin",(int)(remain/60.));
     else
       asprintf(&timer,"%.ds",(int)(remain));
 
-    if(treated!=total)
+    if(treated!=total){
+      printf("\r                                                                                                                    ");
       printf("\r \033[1;31m ******* Progress: %.1f%% | Rate: %.1fk evt/s | Remain: %s *******\033[0m", percent,event_rate/1000.,timer);
-
+    }
     else
       printf("\r \033[1;32m ******* Progress: %.1f%% | Rate: %.1fk evt/s | Remain: %s *******\033[0m", percent,event_rate/1000.,timer);
     
@@ -144,6 +141,6 @@ void ProgressDisplay(clock_t& begin, clock_t& end, unsigned int& treated,unsigne
     begin = clock() ;
     inter=0;
   }
- treated++; 
+  treated++;
  inter++;
 }
diff --git a/NPSimulation/GASPARD/GaspardScorers.cc b/NPSimulation/GASPARD/GaspardScorers.cc
index 5e183b0b7..c9c218567 100644
--- a/NPSimulation/GASPARD/GaspardScorers.cc
+++ b/NPSimulation/GASPARD/GaspardScorers.cc
@@ -534,6 +534,7 @@ G4bool GPDScorerFirstStageFrontStripTrapezoid::ProcessHits(G4Step* aStep, G4Touc
    G4int X = int(temp) + 1;
    //Rare case where particle is close to edge of silicon plan
    if (X == 129) X = 128;
+   
    G4double edep = aStep->GetTotalEnergyDeposit();
    if (edep < TriggerThreshold) return FALSE;
    G4int  index =  aStep->GetTrack()->GetTrackID();
-- 
GitLab