From 325e37133bc0f67d278b5e1b27e0c09a33ce4f4d Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Thu, 26 Nov 2015 14:11:57 +0000
Subject: [PATCH] Fix ROOT 5 backwards compatibility

---
 DDCore/include/DD4hep/Memory.h            | 44 ++++++++-------
 DDG4/include/DDG4/Geant4ActionContainer.h |  6 +-
 DDG4/include/DDG4/Geant4Kernel.h          | 20 ++++---
 DDG4/python/DDG4.py                       |  5 +-
 DDG4/src/Geant4Kernel.cpp                 | 29 +++++++++-
 DDG4/src/python/PyDDG4.cpp                | 12 ++--
 doc/CompileAllOptionPermutations.sh       | 67 +++++++++++++++++++++--
 examples/ClientTests/scripts/MiniTel.py   |  1 -
 8 files changed, 140 insertions(+), 44 deletions(-)

diff --git a/DDCore/include/DD4hep/Memory.h b/DDCore/include/DD4hep/Memory.h
index 8eb461411..639919863 100644
--- a/DDCore/include/DD4hep/Memory.h
+++ b/DDCore/include/DD4hep/Memory.h
@@ -39,28 +39,34 @@ namespace DD4hep  {
   public:
     typedef std::unique_ptr<T> base_t;
 #else
-    : public std::auto_ptr<T>  {
+      : public std::auto_ptr<T>  {
     public:
-      typedef std::auto_ptr<T> base_t;
-      void swap(base_t& c) {
-	this->base_t::operator=(base_t(c.release()));
-      }
+        typedef std::auto_ptr<T> base_t;
+        void swap(base_t& c) {
+          this->base_t::operator=(base_t(c.release()));
+        }
 #endif
     public:
-      /// Default Constructor.
-    dd4hep_ptr() : base_t() {}
-      /// Constructor from pointer
-    dd4hep_ptr(T* p) : base_t(p) {}
-      /// Constructor from copy
-    dd4hep_ptr(base_t& c) : base_t(c) {}
-      /// Assignment operator
-      dd4hep_ptr& operator=(base_t& c) {
-	if ( this != &c )  {
-	  this->swap(c);
-	}
-	return *this;
-      }
-    };
+        /// Default Constructor.
+        dd4hep_ptr() : base_t() {}
+        /// Constructor from pointer
+        dd4hep_ptr(T* p) : base_t(p) {}
+        /// Constructor from copy
+        dd4hep_ptr(base_t& c) : base_t(c) {}
+        /// Assignment operator
+        dd4hep_ptr& operator=(base_t& c) {
+          if ( this != &c )  {
+            this->swap(c);
+          }
+          return *this;
+        }
+        /// Assignment operator
+        dd4hep_ptr& adopt(T* ptr) {
+          base_t smart_ptr(ptr);
+          this->swap(smart_ptr);
+          return *this;
+        }
+      };
   }
 
 #endif  // DD4HEP_MEMORY_H
diff --git a/DDG4/include/DDG4/Geant4ActionContainer.h b/DDG4/include/DDG4/Geant4ActionContainer.h
index d18e80890..2ba51e5b2 100644
--- a/DDG4/include/DDG4/Geant4ActionContainer.h
+++ b/DDG4/include/DDG4/Geant4ActionContainer.h
@@ -95,9 +95,6 @@ namespace DD4hep {
       /// Default destructor
       virtual ~Geant4ActionContainer();
 
-      /// Terminate all associated action instances
-      virtual int terminate();
-
       /// Set the thread's context
       void setContext(Geant4Context* ctxt);
 
@@ -105,6 +102,9 @@ namespace DD4hep {
       /// Thread's Geant4 execution context
       Geant4Context* workerContext();
 
+      /// Terminate all associated action instances
+      virtual int terminate();
+
       /// Access generator action sequence
       Geant4GeneratorActionSequence* generatorAction(bool create);
       /// Access generator action sequence
diff --git a/DDG4/include/DDG4/Geant4Kernel.h b/DDG4/include/DDG4/Geant4Kernel.h
index a98d4cf83..8f61c4051 100644
--- a/DDG4/include/DDG4/Geant4Kernel.h
+++ b/DDG4/include/DDG4/Geant4Kernel.h
@@ -235,29 +235,31 @@ namespace DD4hep {
 
       /// Execute phase action if it exists
       virtual bool executePhase(const std::string& name, const void** args)  const;
+
       /// Construct detector geometry using lcdd plugin
-      void loadGeometry(const std::string& compact_file);
+      virtual void loadGeometry(const std::string& compact_file);
+      /// Load XML file 
+      virtual void loadXML(const char* fname);
 
       /** Geant4 Multi threading support */
       /// Create identified worker instance
-      Geant4Kernel& createWorker();
+      virtual Geant4Kernel& createWorker();
       /// Access worker instance by it's identifier
       Geant4Kernel& worker(unsigned long thread_identifier, bool create_if=false);
       /// Access number of workers
       int numWorkers() const;
 
       /// Run the simulation: Configure Geant4
-      int configure();
+      virtual int configure();
       /// Run the simulation: Initialize Geant4
-      int initialize();
+      virtual int initialize();
       /// Run the simulation: Simulate the number of events given by the property "NumEvents"
-      int run();
+      virtual int run();
       /// Run the simulation: Simulate the number of events "num_events" and modify the property "NumEvents"
-      int runEvents(int num_events);
+      virtual int runEvents(int num_events);
       /// Run the simulation: Terminate Geant4
-      int terminate();
-      /// Load XML file 
-      void loadXML(const char* fname);
+      virtual int terminate();
+      virtual int terminateEx();
     };
     /// Declare property
     template <typename T> Geant4Kernel& Geant4Kernel::declareProperty(const std::string& nam, T& val) {
diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py
index 61c4f4567..920ebc7fd 100644
--- a/DDG4/python/DDG4.py
+++ b/DDG4/python/DDG4.py
@@ -132,13 +132,15 @@ def _kernel_phase(self,name):        return self.addSimplePhase(name,False)
 #---------------------------------------------------------------------------
 def _kernel_worker(self):            return Kernel(self.get().createWorker())
 #---------------------------------------------------------------------------
+def _kernel_terminate(self):         return self.get().terminate()
+#---------------------------------------------------------------------------
 Kernel.phase = _kernel_phase
 Kernel.registerGlobalAction = _registerGlobalAction
 Kernel.registerGlobalFilter = _registerGlobalFilter
 Kernel.createWorker = _kernel_worker
 Kernel.__getattr__ = _getKernelProperty
 Kernel.__setattr__ = _setKernelProperty
-
+Kernel.terminate = _kernel_terminate
 #---------------------------------------------------------------------------
 ActionHandle = Sim.ActionHandle
 #---------------------------------------------------------------------------
@@ -598,5 +600,6 @@ class Geant4:
     #self.master().terminate()
     from ROOT import PyDDG4
     PyDDG4.run(self.master().get())
+    return self
 
 Simple = Geant4
diff --git a/DDG4/src/Geant4Kernel.cpp b/DDG4/src/Geant4Kernel.cpp
index 228a507d7..86d8b6752 100644
--- a/DDG4/src/Geant4Kernel.cpp
+++ b/DDG4/src/Geant4Kernel.cpp
@@ -14,6 +14,7 @@
 
 // Framework include files
 #include "DD4hep/LCDD.h"
+#include "DD4hep/Memory.h"
 #include "DD4hep/Printout.h"
 #include "DD4hep/Primitives.h"
 #include "DD4hep/InstanceCount.h"
@@ -29,15 +30,23 @@
 #include "G4RunManager.hh"
 #endif
 #include "G4UIdirectory.hh"
+#include "G4Threading.hh"
+#include "G4AutoLock.hh"
 
 // C/C++ include files
 #include <stdexcept>
 #include <algorithm>
 #include <pthread.h>
+#include <memory>
 
 using namespace std;
 using namespace DD4hep::Simulation;
 
+namespace {
+  G4Mutex kernel_mutex=G4MUTEX_INITIALIZER;
+  DD4hep::dd4hep_ptr<Geant4Kernel> s_main_instance(0);
+}
+
 /// Standard constructor
 Geant4Kernel::PhaseSelector::PhaseSelector(Geant4Kernel* kernel)
   : m_kernel(kernel) {
@@ -105,13 +114,16 @@ Geant4Kernel::Geant4Kernel(LCDD& lcdd_ref, Geant4Kernel* m, unsigned long ident)
 
 /// Default destructor
 Geant4Kernel::~Geant4Kernel() {
+  if ( this == s_main_instance.get() )   {
+    s_main_instance.release();
+  }
   destroyObjects(m_workers)();
   if ( isMaster() )  {
     releaseObjects(m_globalFilters)();
     releaseObjects(m_globalActions)();
   }
   destroyPhases();
-  deletePtr  (m_runManager);
+  deletePtr(m_runManager);
   Geant4ActionContainer::terminate();
   if ( isMaster() )  {
     m_lcdd.removeExtension < Geant4Kernel > (false);
@@ -122,8 +134,14 @@ Geant4Kernel::~Geant4Kernel() {
 
 /// Instance accessor
 Geant4Kernel& Geant4Kernel::instance(LCDD& lcdd) {
-  static Geant4Kernel obj(lcdd);
-  return obj;
+  if ( 0 == s_main_instance.get() )   {
+    G4AutoLock protection_lock(&kernel_mutex);    {
+      if ( 0 == s_main_instance.get() )   { // Need to check again!
+        s_main_instance.adopt(new Geant4Kernel(lcdd));
+      }
+    }
+  }
+  return *(s_main_instance.get());
 }
 
 #if 0
@@ -288,7 +306,12 @@ int Geant4Kernel::runEvents(int num_events) {
   return Geant4Exec::run(*this);
 }
 
+int Geant4Kernel::terminateEx()  {
+  return this->terminate();
+}
+
 int Geant4Kernel::terminate() {
+  printout(INFO,"Geant4Kernel","++ Terminate Geant4 and delete associated actions.");
   Geant4Exec::terminate(*this);
   destroyPhases();
   for_each(m_globalFilters.begin(), m_globalFilters.end(), releaseObjects(m_globalFilters));
diff --git a/DDG4/src/python/PyDDG4.cpp b/DDG4/src/python/PyDDG4.cpp
index 0068882e5..2179d00af 100644
--- a/DDG4/src/python/PyDDG4.cpp
+++ b/DDG4/src/python/PyDDG4.cpp
@@ -21,10 +21,14 @@
 int PyDDG4::run(Kernel& kernel)  {
   int ret;
   DD4hep::DDPython::AllowThreads allow(0);
-  if ( 1 != (ret=kernel.configure()) )  return ret;
-  if ( 1 != (ret=kernel.initialize()) ) return ret;
-  if ( 1 != (ret=kernel.run()) )        return ret;
-  if ( 1 != (ret=kernel.terminate()) )  return ret;
+  if ( 1 != (ret=kernel.configure()) )
+    return ret;
+  else if ( 1 != (ret=kernel.initialize()) )
+    return ret;
+  else if ( 1 != (ret=kernel.run()) )
+    return ret;
+  else if ( 1 != (ret=kernel.terminate()) )
+    return ret;
     //DD4hep::DDPython::shutdown();
   return ret;
 }
diff --git a/doc/CompileAllOptionPermutations.sh b/doc/CompileAllOptionPermutations.sh
index fcd6f9077..a9115964a 100755
--- a/doc/CompileAllOptionPermutations.sh
+++ b/doc/CompileAllOptionPermutations.sh
@@ -1,13 +1,55 @@
 dir_name=`pwd`;
 SW=/home/frankm/SW;
 
-INSTALL_G4=${SW}/g4_10.01.p02_dbg/lib/Geant4-10.1.2;
 INSTALL_LCIO=${SW}/lcio/v02-04-03;
 INSTALL_XERCESC=${SW}/xercesc;
+
+INSTALL_G4=${SW}/g4_10.01.p02_dbg/lib/Geant4-10.1.2;
 CHECKOUT=${dir_name}/../../DD4hep.trunk/checkout;
-export ROOTSYS=${SW}/root_v6.04.00_dbg;
-export ROOTSYS=${SW}/root_v5.34.25_dbg;
-. ${ROOTSYS}/bin/thisroot.sh;
+GEANT_VERSION=10.01.p02;
+ROOT_VERSION=6.04.00;
+# ==============================================================================
+# Parse arguments
+# ==============================================================================
+parse_command_line_args()
+{
+    MULTITHREADED="";
+    ARG_ERROR="";
+    PLATFORMS="dbg opt";
+    while [[ "$1" == -* ]]; do
+        #echo "Arg:$1 $2";
+        a1=`echo $1 | tr A-Z a-z`;
+	case ${a1} in
+	    -root)
+		ROOT_VERSION=$2;
+		shift
+		;;
+
+	    -geant4)
+		GEANT_VERSION=$2;
+		shift
+		;;
+
+	    -build)
+		PLATFORMS="$2";
+		shift
+		;;
+
+            -mt)
+                MULTITHREADED="YES";
+                ;;
+
+            -st)
+                MULTITHREADED="";
+                ;;
+
+	    *)
+		ARG_ERROR=$1;
+		;;
+	esac
+	shift
+    done
+}
 #cat ${ROOTSYS}/bin/thisroot.sh;
 #
 LINE="==================================================================================================="
@@ -107,4 +149,21 @@ build_all()
     done;
 }
 
+
+parse_command_line_args $*;
+if [ "$ARG_ERROR" != "" ]; then
+    echo "Unknown option: ERROR CONDITION";
+    exit 0;
+elif [ "$ROOT_VERSION" == "" ] || [ "$PLATFORMS" == "" ]; then
+    echo "ERROR CONDITION ROOT_VERSION=${ROOT_VERSION}  PLATFORMS=${PLATFORMS}";
+    exit 0;
+fi;
+export INSTALL_G4=${SW}/g4_${GEANT_VERSION}_dbg/lib/Geant4-10.1.2;
+export ROOTSYS=${SW}/root_v${ROOT_VERSION}_dbg;
+. ${ROOTSYS}/bin/thisroot.sh;
+#
+#
 build_all;
+#
+#
+#
diff --git a/examples/ClientTests/scripts/MiniTel.py b/examples/ClientTests/scripts/MiniTel.py
index b26e588b0..82839d2a3 100644
--- a/examples/ClientTests/scripts/MiniTel.py
+++ b/examples/ClientTests/scripts/MiniTel.py
@@ -55,7 +55,6 @@ def run():
   phys = kernel.physicsList()
   phys.extends = 'QGSP_BERT'
   phys.enableUI()
-  phys.dump()
   # and run
   simple.execute()
 
-- 
GitLab