CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Herwig6Instance.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <sstream>
3 #include <cstdlib>
4 #include <cstring>
5 #include <cctype>
6 #include <string>
7 
8 #ifdef _POSIX_C_SOURCE
9 # include <sys/time.h>
10 # include <signal.h>
11 # include <setjmp.h>
12 #endif
13 
14 #include <CLHEP/Random/RandomEngine.h>
15 
16 #include <HepMC/HerwigWrapper6_4.h>
17 
20 
22 
25 
26 #include "params.inc"
27 
28 using namespace gen;
29 
30 // implementation for the Fortran callbacks from Herwig
31 
32 // this gets a random number from the currently running instance
33 // so, if the have separate instances for let's say decayers based on
34 // Herwig than the Herwig pp collision instance, we get independent
35 // random numbers. Also true for FastSim, since FastSim uses its own
36 // random numbers. This means FastSim needs take a Herwig6Instance
37 // instance of its own instead of calling into Herwig directly.
38 double gen::hwrgen_(int *idummy)
39 { return FortranInstance::getInstance<Herwig6Instance>()->randomEngine->flat(); }
40 
41 void gen::cms_hwwarn_(char fn[6], int *code, int *exit)
42 {
43  std::string function(fn, fn + sizeof fn);
44  *exit = FortranInstance::getInstance<Herwig6Instance>()->hwwarn(function, *code);
45 }
46 
47 extern "C" {
48  void hwaend_()
49  {}
50 
51  void cmsending_(int *ecode)
52  {
53  throw cms::Exception("Herwig6Error")
54  << "Herwig6 stopped run with error code " << *ecode
55  << "." << std::endl;
56  }
57 }
58 
59 // Herwig6Instance methods
60 
62  randomEngine(randomEngine ? randomEngine : &getEngineReference()),
63  timeoutPrivate(0)
64 {
65 }
66 
68  randomEngine(0),
69  timeoutPrivate(0)
70 {
71 }
72 
74 {
75 }
76 
77 // timeout tool
78 
79 #ifdef _POSIX_C_SOURCE
80 // some deep POSIX hackery to catch HERWIG sometimes (O(10k events) with
81 // complicated topologies) getting caught in and endless loop :-(
82 
84 { siglongjmp(*(sigjmp_buf*)FortranInstance::getInstance<Herwig6Instance>()->timeoutPrivate, 1); }
85 
86 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)())
87 {
88  if (timeoutPrivate)
89  throw cms::Exception("ReentrancyProblem")
90  << "Herwig6Instance::timeout() called recursively."
91  << std::endl;
92  struct sigaction saOld;
93  std::memset(&saOld, 0, sizeof saOld);
94 
95  struct itimerval itv;
96  timerclear(&itv.it_value);
97  timerclear(&itv.it_interval);
98  itv.it_value.tv_sec = 0;
99  itv.it_interval.tv_sec = 0;
100  setitimer(ITIMER_VIRTUAL, &itv, NULL);
101 
102  sigset_t ss;
103  sigemptyset(&ss);
104  sigaddset(&ss, SIGVTALRM);
105 
106  sigprocmask(SIG_UNBLOCK, &ss, NULL);
107  sigprocmask(SIG_BLOCK, &ss, NULL);
108 
109  timeoutPrivate = new sigjmp_buf;
110  if (sigsetjmp(*(sigjmp_buf*)timeoutPrivate, 1)) {
111  delete (sigjmp_buf*)timeoutPrivate;
112  timeoutPrivate = 0;
113 
114  itv.it_value.tv_sec = 0;
115  itv.it_interval.tv_sec = 0;
116  setitimer(ITIMER_VIRTUAL, &itv, NULL);
117  sigprocmask(SIG_UNBLOCK, &ss, NULL);
118  return true;
119  }
120 
121  itv.it_value.tv_sec = secs;
122  itv.it_interval.tv_sec = secs;
123  setitimer(ITIMER_VIRTUAL, &itv, NULL);
124 
125  struct sigaction sa;
126  std::memset(&sa, 0, sizeof sa);
127  sa.sa_handler = &Herwig6Instance::_timeout_sighandler;
128  sa.sa_flags = SA_ONESHOT;
129  sigemptyset(&sa.sa_mask);
130 
131  sigaction(SIGVTALRM, &sa, &saOld);
132  sigprocmask(SIG_UNBLOCK, &ss, NULL);
133 
134  try {
135  fn();
136  } catch(...) {
137  delete (sigjmp_buf*)timeoutPrivate;
138  timeoutPrivate = 0;
139 
140  itv.it_value.tv_sec = 0;
141  itv.it_interval.tv_sec = 0;
142  setitimer(ITIMER_VIRTUAL, &itv, NULL);
143 
144  sigaction(SIGVTALRM, &saOld, NULL);
145 
146  throw;
147  }
148 
149  delete (sigjmp_buf*)timeoutPrivate;
150  timeoutPrivate = 0;
151 
152  itv.it_value.tv_sec = 0;
153  itv.it_interval.tv_sec = 0;
154  setitimer(ITIMER_VIRTUAL, &itv, NULL);
155 
156  sigaction(SIGVTALRM, &saOld, NULL);
157 
158  return false;
159 }
160 #else
161 bool Herwig6Instance::timeout(unsigned int secs, void (*fn)())
162 {
163  fn();
164  return false;
165 }
166 #endif
167 
168 bool Herwig6Instance::hwwarn(const std::string &fn, int code)
169 {
170  return false;
171 }
172 
173 // regular Herwig6Instance methods
174 
175 bool Herwig6Instance::give(const std::string &line)
176 {
177  typedef std::istringstream::traits_type traits;
178 
179  const char *p = line.c_str(), *q;
180  p += std::strspn(p, " \t\r\n");
181 
182  for(q = p; std::isalnum(*q); q++);
183  std::string name(p, q - p);
184 
185  const ConfigParam *param;
186  for(param = configParams; param->name; param++)
187  if (name == param->name)
188  break;
189  if (!param->name)
190  return false;
191 
192  p = q + std::strspn(q, " \t\r\n");
193 
194  std::size_t pos = 0;
195  std::size_t mult = 1;
196  for(unsigned int i = 0; i < 3; i++) {
197  if (!param->dim[i].size)
198  break;
199 
200  if (*p++ != (i ? ',' : '('))
201  return false;
202 
203  p += std::strspn(p, " \t\r\n");
204 
205  for(q = p; std::isdigit(*q); q++);
206  std::istringstream ss(std::string(p, q - p));
207  std::size_t index;
208  ss >> index;
209  if (ss.bad() || ss.peek() != traits::eof())
210  return false;
211 
212  if (index < param->dim[i].offset)
213  return false;
214  index -= param->dim[i].offset;
215  if (index >= param->dim[i].size)
216  return false;
217 
218  p = q + std::strspn(q, " \t\r\n");
219 
220  pos += mult * index;
221  mult *= param->dim[i].size;
222  }
223 
224  if (param->dim[0].size) {
225  if (*p++ != ')')
226  return false;
227  p += std::strspn(p, " \t\r\n");
228  }
229 
230  if (*p++ != '=')
231  return false;
232  p += std::strspn(p, " \t\r\n");
233 
234  for(q = p; *q && (std::isalnum(*q) || std::strchr(".-+", *q)); q++);
235  std::istringstream ss(std::string(p, q - p));
236 
237  p = q + std::strspn(q, " \t\r\n");
238  if (*p && *p != '!')
239  return false;
240 
241  switch(param->type) {
242  case kInt: {
243  int value;
244  ss >> value;
245  if (ss.bad() || ss.peek() != traits::eof())
246  return false;
247 
248  ((int*)param->ptr)[pos] = value;
249  break;
250  }
251  case kDouble: {
252  double value;
253  ss >> value;
254  if (ss.bad() || ss.peek() != traits::eof())
255  return false;
256 
257  ((double*)param->ptr)[pos] = value;
258  break;
259  }
260  case kLogical: {
261  std::string value_;
262  ss >> value_;
263  if (ss.bad() || ss.peek() != traits::eof())
264  return false;
265 
266  for(std::string::iterator iter = value_.begin();
267  iter != value_.end(); ++iter)
268  *iter = std::tolower(*iter);
269  bool value;
270  if (value_ == "yes" || value_ == "true" || value_ == "1")
271  value = true;
272  else if (value_ == "no" || value_ == "false" || value_ == "0")
273  value = false;
274  else
275  return false;
276 
277  ((int*)param->ptr)[pos] = value;
278  break;
279  }
280  }
281 
282  return true;
283 }
Herwig6Instance(CLHEP::HepRandomEngine *randomEngine=0)
int i
Definition: DBlmapReader.cc:9
bool timeout(unsigned int secs, void(*fn)())
static void _timeout_sighandler(int signr)
#define NULL
Definition: scimark2.h:8
CLHEP::HepRandomEngine & getEngineReference()
double p[5][pyjets_maxn]
void hwaend_()
Definition: Dummies.cc:10
void cmsending_(int *ecode)
Definition: Dummies.cc:12
CLHEP::HepRandomEngine * randomEngine
Definition: PYR.cc:4
unsigned int offset(bool)
bool give(const std::string &line)
void cms_hwwarn_(char fn[6], int *, int *)
virtual bool hwwarn(const std::string &fn, int code)
double hwrgen_(int *)