DD4hep - The AIDA detector description toolkit for high energy physics experiments
DD4hep  Rev:Unversioneddirectory
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Geant4Handle.cpp
Go to the documentation of this file.
1 // $Id: $
2 //==========================================================================
3 // AIDA Detector description implementation for LCD
4 //--------------------------------------------------------------------------
5 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
6 // All rights reserved.
7 //
8 // For the licensing terms see $DD4hepINSTALL/LICENSE.
9 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
10 //
11 // Author : M.Frank
12 //
13 //==========================================================================
14 
15 // Framework include files
16 #include "DD4hep/LCDD.h"
17 #include "DD4hep/Plugins.h"
18 #include "DD4hep/Printout.h"
19 
20 #include "DDG4/Geant4Handle.h"
21 #include "DDG4/Geant4Kernel.h"
23 #include "DDG4/Geant4RunAction.h"
24 #include "DDG4/Geant4EventAction.h"
29 #include "DDG4/Geant4PhysicsList.h"
30 #include "DDG4/Geant4ActionPhase.h"
33 
34 // Geant4 include files
35 #include "G4Threading.hh"
36 #include "G4AutoLock.hh"
37 
38 // C/C++ include files
39 #include <stdexcept>
40 
41 using namespace std;
42 using namespace DD4hep;
43 using namespace DD4hep::Simulation;
44 namespace {
45  G4Mutex creation_mutex=G4MUTEX_INITIALIZER;
46 }
47 
48 namespace DD4hep {
49  namespace Simulation {
50 
51 
52  template <typename TYPE> static inline TYPE* checked_value(TYPE* p) {
53  if (p) {
54  return p;
55  }
56  throw runtime_error(format("Geant4Handle", "Attempt to access an invalid object of type:%s!", typeName(typeid(TYPE)).c_str()));
57  }
58 
59  template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle()
60  : value(0) {
61  }
62 
63  template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle(TYPE* typ)
64  : value(typ) {
65  if (value)
66  value->addRef();
67  }
68 
70  : value(0) {
71  value = handle.get();
72  if (value)
73  value->addRef();
74  }
75 
76  template <typename TYPE> TYPE* _create_object(Geant4Kernel& kernel, const TypeName& typ) {
77  Geant4Context* ctxt = kernel.workerContext();
78  Geant4Action* object = PluginService::Create<Geant4Action*>(typ.first, ctxt, typ.second);
79  if (!object && typ.first == typ.second) {
80  string _t = typeName(typeid(TYPE));
81  printout(DEBUG, "Geant4Handle", "Object factory for %s not found. Try out %s",
82  typ.second.c_str(), _t.c_str());
83  object = PluginService::Create<Geant4Action*>(_t, ctxt, typ.second);
84  if (!object) {
85  size_t idx = _t.rfind(':');
86  if (idx != string::npos)
87  _t = string(_t.substr(idx + 1));
88  printout(DEBUG, "Geant4Handle", "Try out object factory for %s",_t.c_str());
89  object = PluginService::Create<Geant4Action*>(_t, ctxt, typ.second);
90  }
91  }
92  if (object) {
93  TYPE* ptr = dynamic_cast<TYPE*>(object);
94  if (ptr) {
95  return ptr;
96  }
97  throw runtime_error(format("Geant4Handle", "Failed to convert object of type %s to handle of type %s!",
98  typ.first.c_str(),typ.second.c_str()));
99  }
100  throw runtime_error(format("Geant4Handle", "Failed to create object of type %s!", typ.first.c_str()));
101  }
102 
103  template <typename TYPE, typename CONT>
105  CONT& (Geant4ActionContainer::*pmf)(),
106  const string& type_name,
107  const string& shared_typ,
108  bool shared, TYPE*)
109  {
110  TypeName typ = TypeName::split(type_name);
111  Geant4Kernel& k = shared ? kernel.master() : kernel;
112  if ( shared && k.isMultiThreaded() ) {
113  typedef typename TYPE::shared_type _ST;
114  TypeName s_type = TypeName::split(shared_typ+"/"+typ.second);
115  _ST* object = (_ST*)_create_object<TYPE>(kernel,s_type);
116  CONT& container = (k.*pmf)();
117  TYPE* value = 0;
118  // Need to protect the global action sequence!
119  G4AutoLock protection_lock(&creation_mutex); {
120  value = container.get(typ.second);
121  if ( !value ) value = _create_object<TYPE>(k,typ);
122  container.adopt(value);
123  }
124  object->use(value);
125  value->info("+++ Created shared object for %s of type %s.",
126  typ.second.c_str(),typeName(typeid(TYPE)).c_str());
127  return object;
128  }
129  TYPE* value = _create_object<TYPE>(k,typ);
130  return value;
131  }
132 
133  template <typename TYPE>
134  Geant4Handle<TYPE>::Geant4Handle(Geant4Kernel& kernel, const string& type_name, bool /* shared */) {
135  value = _create_object<TYPE>(kernel,TypeName::split(type_name));
136  }
137 
138  template <typename TYPE>
139  Geant4Handle<TYPE>::Geant4Handle(Geant4Kernel& kernel, const char* type_name_char, bool /* shared */) {
140  value = _create_object<TYPE>(kernel,TypeName::split(type_name_char ? type_name_char : "????"));
141  }
142 
143  template <typename TYPE> Geant4Handle<TYPE>::~Geant4Handle() {
144  if (value)
145  value->release();
146  value = 0;
147  }
148 
149  template <typename TYPE> TYPE* Geant4Handle<TYPE>::release() {
150  TYPE* temp = value;
151  value = 0;
152  return temp;
153  }
154 
155  template <typename TYPE> void Geant4Handle<TYPE>::checked_assign(TYPE* p) {
156  if (value)
157  value->release();
158  value = checked_value(p);
159  if (value)
160  value->addRef();
161  }
162 
163  template <typename TYPE> Property& Geant4Handle<TYPE>::operator[](const string& property_name) const {
164  PropertyManager& pm = checked_value(value)->properties();
165  return pm[property_name];
166  }
167 
168  template <typename TYPE> Geant4Handle<TYPE>::operator TYPE*() const {
169  return checked_value(value);
170  }
171 
172  template <typename TYPE> bool Geant4Handle<TYPE>::operator!() const {
173  return 0 == value;
174  }
175 
176  template <typename TYPE> TYPE* Geant4Handle<TYPE>::get() const {
177  return checked_value(value);
178  }
179 
180  template <typename TYPE> TYPE* Geant4Handle<TYPE>::operator->() const {
181  return checked_value(value);
182  }
183 
184  template <typename TYPE> Geant4Action* Geant4Handle<TYPE>::action() const {
185  return checked_value(value);
186  }
187 
189  if ( &handle != this ) {
190  if (value) value->release();
191  value = handle.get();
192  if (value) value->addRef();
193  }
194  return *this;
195  }
196 
197  template <typename TYPE> Geant4Handle<TYPE>& Geant4Handle<TYPE>::operator=(TYPE* typ) {
198  if ( typ != value ) {
199  if (value) value->release();
200  value = typ;
201  if (value) value->addRef();
202  }
203  return *this;
204  }
205 
206  //namespace DD4hep {
207  // namespace Simulation {
208 
211  }
213  }
216  if ( k ) return KernelHandle(k);
217  throw runtime_error(format("KernelHandle", "Cannot access worker context [Invalid Handle]"));
218  }
220  if ( value ) delete value;
221  value = 0;
222  }
223 
224  template <>
225  Geant4Handle<Geant4RunAction>::Geant4Handle(Geant4Kernel& kernel, const string& type_name, bool shared) {
226  value = _create_share(kernel,&Geant4ActionContainer::runAction,type_name,"Geant4SharedRunAction",shared,(handled_type*)0);
227  }
228  template <>
229  Geant4Handle<Geant4RunAction>::Geant4Handle(Geant4Kernel& kernel, const char* type_name, bool shared) {
230  value = _create_share(kernel,&Geant4ActionContainer::runAction,type_name,"Geant4SharedRunAction",shared,(handled_type*)0);
231  }
232 
233  template <>
234  Geant4Handle<Geant4EventAction>::Geant4Handle(Geant4Kernel& kernel, const string& type_name, bool shared) {
235  value = _create_share(kernel,&Geant4ActionContainer::eventAction,type_name,"Geant4SharedEventAction",shared,(handled_type*)0);
236  }
237  template <>
238  Geant4Handle<Geant4EventAction>::Geant4Handle(Geant4Kernel& kernel, const char* type_name, bool shared) {
239  value = _create_share(kernel,&Geant4ActionContainer::eventAction,type_name,"Geant4SharedEventAction",shared,(handled_type*)0);
240  }
241 
242  template <>
243  Geant4Handle<Geant4GeneratorAction>::Geant4Handle(Geant4Kernel& kernel, const string& type_name, bool shared) {
244  value = _create_share(kernel,&Geant4ActionContainer::generatorAction,type_name,"Geant4SharedGeneratorAction",shared,(handled_type*)0);
245  }
246  template <>
247  Geant4Handle<Geant4GeneratorAction>::Geant4Handle(Geant4Kernel& kernel, const char* type_name, bool shared) {
248  value = _create_share(kernel,&Geant4ActionContainer::generatorAction,type_name,"Geant4SharedGeneratorAction",shared,(handled_type*)0);
249  }
250 
251  template <>
252  Geant4Handle<Geant4TrackingAction>::Geant4Handle(Geant4Kernel& kernel, const string& type_name, bool shared) {
253  value = _create_share(kernel,&Geant4ActionContainer::trackingAction,type_name,"Geant4SharedTrackingAction",shared,(handled_type*)0);
254  }
255  template <>
256  Geant4Handle<Geant4TrackingAction>::Geant4Handle(Geant4Kernel& kernel, const char* type_name, bool shared) {
257  value = _create_share(kernel,&Geant4ActionContainer::trackingAction,type_name,"Geant4SharedTrackingAction",shared,(handled_type*)0);
258  }
259 
260  template <>
261  Geant4Handle<Geant4SteppingAction>::Geant4Handle(Geant4Kernel& kernel, const string& type_name, bool shared) {
262  value = _create_share(kernel,&Geant4ActionContainer::steppingAction,type_name,"Geant4SharedSteppingAction",shared,(handled_type*)0);
263  }
264  template <>
265  Geant4Handle<Geant4SteppingAction>::Geant4Handle(Geant4Kernel& kernel, const char* type_name, bool shared) {
266  value = _create_share(kernel,&Geant4ActionContainer::steppingAction,type_name,"Geant4SharedSteppingAction",shared,(handled_type*)0);
267  }
268 
269  template <>
270  Geant4Handle<Geant4StackingAction>::Geant4Handle(Geant4Kernel& kernel, const string& type_name, bool shared) {
271  value = _create_share(kernel,&Geant4ActionContainer::stackingAction,type_name,"Geant4SharedStackingAction",shared,(handled_type*)0);
272  }
273  template <>
274  Geant4Handle<Geant4StackingAction>::Geant4Handle(Geant4Kernel& kernel, const char* type_name, bool shared) {
275  value = _create_share(kernel,&Geant4ActionContainer::stackingAction,type_name,"Geant4SharedStackingAction",shared,(handled_type*)0);
276  }
277 
278  template <> Geant4Handle<Geant4Sensitive>::Geant4Handle(Geant4Kernel& kernel, const string& type_name,
279  const string& detector, bool /* shared */) {
280  try {
281  Geant4Context* ctxt = kernel.workerContext();
282  TypeName typ = TypeName::split(type_name);
283  Geometry::LCDD& lcdd = kernel.lcdd();
284  Geometry::DetElement det = lcdd.detector(detector);
285  Geant4Sensitive* object = PluginService::Create<Geant4Sensitive*>(typ.first, ctxt, typ.second, &det, &lcdd);
286  if (object) {
287  value = object;
288  return;
289  }
290  }
291  catch (const exception& e) {
292  printout(ERROR, "Geant4Handle<Geant4Sensitive>", "Exception: %s", e.what());
293  }
294  catch (...) {
295  printout(ERROR, "Geant4Handle<Geant4Sensitive>", "Exception: Unknown exception");
296  }
297  throw runtime_error(format("Geant4Handle<Geant4Sensitive>",
298  "Failed to create sensitive object of type %s for detector %s!",
299  type_name.c_str(), detector.c_str()));
300  }
301 
302 
303  template class Geant4Handle<Geant4Action>;
304  template class Geant4Handle<Geant4Filter>;
305  template class Geant4Handle<Geant4Sensitive>;
306  template class Geant4Handle<Geant4ActionPhase>;
307  template class Geant4Handle<Geant4PhaseAction>;
309  template class Geant4Handle<Geant4RunAction>;
310  template class Geant4Handle<Geant4EventAction>;
311  template class Geant4Handle<Geant4TrackingAction>;
312  template class Geant4Handle<Geant4SteppingAction>;
313  template class Geant4Handle<Geant4StackingAction>;
315  template class Geant4Handle<Geant4PhysicsList>;
317 
328  }
329 }
handled_type * operator->() const
Access to the underlying object.
Geant4Handle & operator=(const Geant4Handle &handle)
Assignment operator.
The property class to assign options to actions.
Geant4Kernel & worker(unsigned long thread_identifier, bool create_if=false)
Access worker instance by it's identifier.
static unsigned long int thread_self()
Access thread identifier.
Geant4StackingActionSequence & stackingAction()
Access stacking action sequence.
bool operator!() const
Validity check.
handled_type * value
Pointer to referenced object.
Definition: Geant4Handle.h:97
Helper class to handle strings of the format "type/name".
Definition: Geant4Action.h:62
std::string typeName(const std::type_info &type)
ABI information about type names.
Definition: Primitives.cpp:186
TYPE * _create_share(Geant4Kernel &kernel, CONT &(Geant4ActionContainer::*pmf)(), const string &type_name, const string &shared_typ, bool shared, TYPE *)
static TYPE * checked_value(TYPE *p)
handled_type * value
Pointer to referenced object.
Definition: Geant4Handle.h:48
LCDD & lcdd() const
Access to detector description.
Definition: Geant4Kernel.h:153
static LCDD & getInstance(void)
—Factory method----—
Definition: LCDDImp.cpp:87
Geant4EventActionSequence & eventAction()
Access run action sequence.
return e
Definition: Volumes.cpp:297
Property & operator[](const std::string &property_name) const
Property accessor.
Handle to Geant4 actions with built-in creation mechanism.
Definition: Geant4Config.h:29
std::string format(const std::string &src, const std::string &fmt,...)
Build formatted string.
Definition: Printout.cpp:267
virtual DetElement detector(const std::string &name) const =0
Retrieve a field component by it's name from the detector description.
The base class for Geant4 sensitive detector actions implemented by users.
Class, which allows all Geant4Action derivatives to access the DDG4 kernel structures.
Definition: Geant4Kernel.h:43
KernelHandle worker()
Access to worker thread.
Class, which allows all Geant4Action to be stored.
Geant4GeneratorActionSequence & generatorAction()
Access generator action sequence.
Geant4Kernel & master() const
Thread's master context.
Definition: Geant4Kernel.h:107
handled_type * get() const
Access to the underlying object.
Geant4Action * action() const
Access to the underlying object.
handled_type * release()
Release the underlying object.
Geant4Context * workerContext()
Thread's Geant4 execution context.
TYPE * _create_object(Geant4Kernel &kernel, const TypeName &typ)
void destroy()
Destroy referenced object (program termination)
static TypeName split(const std::string &type_name)
Split string pair according to default delimiter ('/')
Handle class describing a detector element.
Definition: Detector.h:172
Geant4TrackingActionSequence & trackingAction()
Access tracking action sequence.
Generic context to extend user, run and event information.
Handle to Geant4 actions with built-in creation mechanism.
Definition: Geant4Handle.h:93
~Geant4Handle()
Default destructor.
The main interface to the DD4hep detector description package.
Definition: LCDD.h:82
Geant4RunActionSequence & runAction()
Access run action sequence.
void handle(const O *o, const C &c, F pmf)
int printout(PrintLevel severity, const char *src, const char *fmt,...)
Calls the display action with a given severity level.
Definition: Printout.cpp:111
Geant4Handle()
Default constructor.
KernelHandle()
Default constructor.
static Geant4Kernel & instance(LCDD &lcdd)
Instance accessor.
Manager to ease the handling of groups of properties.
Default base class for all Geant 4 actions and derivates thereof.
Definition: Geant4Action.h:91
Geant4SteppingActionSequence & steppingAction()
Access stepping action sequence.