gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
exceptions.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
19 
20 #include <string>
21 #include <iostream>
22 #include <algorithm>
23 #include <omp.h>
24 
29 #include "gambit/Logs/logger.hpp"
30 
31 namespace Gambit
32 {
33  using namespace std;
34  using namespace LogTags;
35  typedef std::string str;
36 
37  // Public members of GAMBIT exception base class.
38 
40  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal) :
41  myKind (kind),
42  myWhat (what),
43  myShortWhat (what),
44  myMessage (message),
45  isFatal (fatal)
46  {
47  exception_map()[inikey] = this;
48  }
49 
51  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal,
52  LogTag t1) :
53  myKind (kind),
54  myWhat (what),
55  myShortWhat (what),
56  myMessage (message),
57  isFatal (fatal)
58  {
59  myLogTags.insert(t1);
60  exception_map()[inikey] = this;
61  }
62 
64  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal,
65  LogTag t1, LogTag t2) :
66  myKind (kind),
67  myWhat (what),
68  myShortWhat (what),
69  myMessage (message),
70  isFatal (fatal)
71  {
72  myLogTags.insert(t1);
73  myLogTags.insert(t2);
74  exception_map()[inikey] = this;
75  }
76 
78  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal,
79  LogTag t1, LogTag t2, LogTag t3) :
80  myKind (kind),
81  myWhat (what),
82  myShortWhat (what),
83  myMessage (message),
84  isFatal (fatal)
85  {
86  myLogTags.insert(t1);
87  myLogTags.insert(t2);
88  myLogTags.insert(t3);
89  exception_map()[inikey] = this;
90  }
91 
93  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal,
94  LogTag t1, LogTag t2, LogTag t3, LogTag t4) :
95  myKind (kind),
96  myWhat (what),
97  myShortWhat (what),
98  myMessage (message),
99  isFatal (fatal)
100  {
101  myLogTags.insert(t1);
102  myLogTags.insert(t2);
103  myLogTags.insert(t3);
104  myLogTags.insert(t4);
105  exception_map()[inikey] = this;
106  }
107 
109  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal,
110  LogTag t1, LogTag t2, LogTag t3, LogTag t4, LogTag t5) :
111  myKind (kind),
112  myWhat (what),
113  myShortWhat (what),
114  myMessage (message),
115  isFatal (fatal)
116  {
117  myLogTags.insert(t1);
118  myLogTags.insert(t2);
119  myLogTags.insert(t3);
120  myLogTags.insert(t4);
121  myLogTags.insert(t5);
122  exception_map()[inikey] = this;
123  }
124 
126  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal,
127  LogTag t1, LogTag t2, LogTag t3, LogTag t4, LogTag t5, LogTag t6) :
128  myKind (kind),
129  myWhat (what),
130  myShortWhat (what),
131  myMessage (message),
132  isFatal (fatal)
133  {
134  myLogTags.insert(t1);
135  myLogTags.insert(t2);
136  myLogTags.insert(t3);
137  myLogTags.insert(t4);
138  myLogTags.insert(t5);
139  myLogTags.insert(t6);
140  exception_map()[inikey] = this;
141  }
142 
144  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal,
145  LogTag t1, LogTag t2, LogTag t3, LogTag t4, LogTag t5, LogTag t6, LogTag t7) :
146  myKind (kind),
147  myWhat (what),
148  myShortWhat (what),
149  myMessage (message),
150  isFatal (fatal)
151  {
152  myLogTags.insert(t1);
153  myLogTags.insert(t2);
154  myLogTags.insert(t3);
155  myLogTags.insert(t4);
156  myLogTags.insert(t5);
157  myLogTags.insert(t6);
158  myLogTags.insert(t7);
159  exception_map()[inikey] = this;
160  }
161 
163  exception::exception(const char* kind, const char* what, const char* message, const char* inikey, bool fatal, std::set<LogTag> tags) :
164  myLogTags (tags),
165  myKind (kind),
166  myWhat (what),
167  myShortWhat (what),
168  myMessage (message),
169  isFatal (fatal)
170  {
171  exception_map()[inikey] = this;
172  }
173 
175  void exception::set_fatal(bool fatal)
176  {
177  #pragma omp critical (GAMBIT_exception)
178  {
179  isFatal = fatal;
180  }
181  }
182 
184  const char* exception::what() const throw()
185  {
186  return myWhat.c_str();
187  }
188 
192  void exception::raise(const std::string& origin, const std::string& specific_message)
193  {
194  str full_message = isFatal ? specific_message+parameters : specific_message;
195  #pragma omp critical (GAMBIT_exception)
196  {
197  log_exception(origin, full_message);
198  }
199  if (isFatal) throw_iff_outside_parallel();
200  }
201 
203  void exception::forced_throw(const std::string& origin, const std::string& specific_message)
204  {
205  #pragma omp critical (GAMBIT_exception)
206  {
207  log_exception(origin, specific_message+parameters);
208  }
209  throw(*this);
210  }
211 
213  void exception::silent_forced_throw()
214  {
215  throw(*this);
216  }
217 
219  const std::map<const char*,exception*>& exception::all_exceptions()
220  {
221  return exception_map();
222  }
223 
225  void exception::set_parameters(str params)
226  {
227  parameters = params;
228  }
229 
230  // Private members of GAMBIT exception base class.
231 
233  std::map<const char*,exception*>& exception::exception_map()
234  {
235  static std::map<const char*,exception*> local_map;
236  return local_map;
237  }
238 
240  void exception::log_exception(const std::string& origin, const std::string& specific_message)
241  {
242  std::ostringstream msg;
243  msg << myKind << ": " << myMessage << std::endl
244  << specific_message << std::endl
245  << "Raised at: " << origin << ".";
246  if (isFatal)
247  {
248  logger() << fatal;
249  std::ostringstream myLongWhat;
250  myLongWhat << myShortWhat << std::endl << msg.str();
251  myWhat = myLongWhat.str();
252  }
253  else
254  {
255  logger() << nonfatal;
256  myWhat = myShortWhat;
257  }
258  for (std::set<LogTag>::iterator it = myLogTags.begin(); it != myLogTags.end(); ++it) { logger() << *it; }
259  logger() << msg.str() << EOM;
260  }
261 
263  void exception::throw_iff_outside_parallel()
264  {
265  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
266  {
267  throw(*this);
268  }
269  else
270  {
271  abort_here_and_now(); // If in an OpenMP parallel block, just abort immediately.
272  }
273  }
274 
276  void exception::abort_here_and_now()
277  {
278  #pragma omp critical (GAMBIT_exception)
279  {
280  cerr << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl
281  << "GAMBIT has exited with fatal exception: " << what() << endl
282  << "Please note: this error occurred inside an OpenMP parallel " << endl
283  << "region and so caused a hard stop. If you are running in MPI " << endl
284  << "mode, other processes were not informed of this error and " << endl
285  << "may have to be killed manually (though your MPI implementation " << endl
286  << "may automatically kill them). For more 'gentle' handling of " << endl
287  << "errors in OpenMP loops, please raise errors using the Piped_exceptions system." << endl;
288  #ifdef WITH_MPI
289  GMPI::Comm().Abort();
290  #else
291  abort();
292  #endif
293  }
294  }
295 
296 
298 
300  error::error(const char* message, const char* inikey) :
301  exception("ERROR", "GAMBIT error", message, inikey, true, err) {}
303  error::error(const char* message, const char* inikey, LogTag t1)
304  : exception("ERROR", "GAMBIT error", message, inikey, true, err, t1) {}
306  error::error(const char* message, const char* inikey, LogTag t1, LogTag t2)
307  : exception("ERROR", "GAMBIT error", message, inikey, true, err, t1, t2) {}
309  error::error(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3)
310  : exception("ERROR", "GAMBIT error", message, inikey, true, err, t1, t2, t3) {}
312  error::error(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3, LogTag t4)
313  : exception("ERROR", "GAMBIT error", message, inikey, true, err, t1, t2, t3, t4) {}
315  error::error(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3, LogTag t4, LogTag t5)
316  : exception("ERROR", "GAMBIT error", message, inikey, true, err, t1, t2, t3, t4, t5) {}
318  error::error(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3, LogTag t4, LogTag t5, LogTag t6)
319  : exception("ERROR", "GAMBIT error", message, inikey, true, err, t1, t2, t3, t4, t5, t6) {}
321  error::error(const char* message, const char* inikey, std::set<LogTag> tags) :
322  exception("ERROR", "GAMBIT error", message, inikey, true)
323  {
324  myLogTags = tags;
325  myLogTags.insert(err);
326  }
327 
329 
331  warning::warning(const char* message, const char* inikey) :
332  exception("WARNING", "GAMBIT warning", message, inikey, false, warn) {}
334  warning::warning(const char* message, const char* inikey, LogTag t1)
335  : exception("WARNING", "GAMBIT warning", message, inikey, false, warn, t1) {}
337  warning::warning(const char* message, const char* inikey, LogTag t1, LogTag t2)
338  : exception("WARNING", "GAMBIT warning", message, inikey, false, warn, t1, t2) {}
340  warning::warning(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3)
341  : exception("WARNING", "GAMBIT warning", message, inikey, false, warn, t1, t2, t3) {}
343  warning::warning(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3, LogTag t4)
344  : exception("WARNING", "GAMBIT warning", message, inikey, false, warn, t1, t2, t3, t4) {}
346  warning::warning(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3, LogTag t4, LogTag t5)
347  : exception("WARNING", "GAMBIT warning", message, inikey, false, warn, t1, t2, t3, t4, t5) {}
349  warning::warning(const char* message, const char* inikey, LogTag t1, LogTag t2, LogTag t3, LogTag t4, LogTag t5, LogTag t6)
350  : exception("WARNING", "GAMBIT warning", message, inikey, false, warn, t1, t2, t3, t4, t5, t6) {}
352  warning::warning(const char* message, const char* inikey, std::set<LogTag> tags) :
353  exception("WARNING", "GAMBIT warning", message, inikey, false)
354  {
355  myLogTags = tags;
356  myLogTags.insert(warn);
357  }
358 
359 
361 
363  special_exception::special_exception(const char* what) : myWhat(what), myMessage("") {}
364 
366  const char* special_exception::what() const throw()
367  {
368  const char* temp;
369  temp = myWhat;
370  return temp;
371  }
372 
375  {
376  std::string temp;
377  #pragma omp critical (GAMBIT_exception)
378  {
379  temp = myMessage;
380  }
381  return temp;
382  }
383 
385  void special_exception::raise(const std::string& msg)
386  {
387  #pragma omp critical (GAMBIT_exception)
388  {
389  myMessage = msg;
390  }
391  throw(*this);
392  }
393 
394 
396 
398  invalid_point_exception::invalid_point_exception() : special_exception("GAMBIT invalid point."), myThrower(NULL) {}
399 
402  {
403  #pragma omp critical (myThrower)
404  {
405  myThrower = thrown_from;
406  }
407  }
408 
411  {
412  functor* temp;
413  #pragma omp critical (myThrower)
414  {
415  temp = myThrower;
416  }
417  if (temp == NULL) utils_error().raise(LOCAL_INFO, "No throwing functor in invalid_point_exception.");
418  return temp;
419  }
420 
422  void invalid_point_exception::raise(const std::string& msg)
423  {
424  // Default code is 1
425  raise(msg, 1);
426  }
427 
429  void invalid_point_exception::raise(const std::string& msg, const int mycode)
430  {
431  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
432  {
433  #pragma omp critical (GAMBIT_exception)
434  {
435  myMessage = msg;
436  }
437  invalidcode = mycode;
438  throw(*this);
439  }
440  else
441  {
442  std::ostringstream full_msg;
443  full_msg << "Sorry, you cannot raise an invalid point exception inside an OpenMP block." << endl
444  << "Please use piped_invalid_point.request() in your block, then check it with " << endl
445  << "piped_invalid_point.check() to raise the exception outside the block." << endl
446  << "Message: " << msg;
447  #pragma omp critical (GAMBIT_exception)
448  {
449  myMessage = full_msg.str();
450  }
451  abort_here_and_now(); // If in an OpenMP parallel block, just abort immediately.
452  }
453  }
454 
457  {
458  #pragma omp critical (GAMBIT_invalid_pt_exception)
459  {
460  cerr << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl;
461  cerr << "An invalid_point exception is fatal inside an OpenMP block. " << endl << what() << endl << message() << endl;
462  #ifdef WITH_MPI
463  GMPI::Comm().Abort();
464  #else
465  abort();
466  #endif
467  }
468  }
469 
471  void Piped_invalid_point::request(std::string message)
472  {
473  #pragma omp critical (GAMBIT_piped_invalid_point)
474  {
475  this->message = message;
476  this->flag = true;
477  }
478  }
479 
482  {
483  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
484  {
485  if (this->flag)
486  {
487  this->flag = false; // Reset...
488  invalid_point().raise(this->message); // ...and throw.
489  }
490  }
491  else
492  {
493  #pragma omp critical (GAMBIT_invalid_point)
494  {
495  cerr << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl;
496  cerr << "GAMBIT has exited with fatal exception: Piped_invalid_point::check() called inside an OpenMP block." << endl
497  << "Piped exceptions may be requested inside OpenMP blocks, but should only be checked outside the block." << endl;
498  if (this->flag)
499  cerr << "Invalid point message requested: " << endl << this->message;
500  else cerr << "No invalid point requested." << endl;
501  #ifdef WITH_MPI
502  GMPI::Comm().Abort();
503  #else
504  abort();
505  #endif
506  }
507  }
508  }
509 
511 
513  halt_loop_exception::halt_loop_exception() : special_exception("Immediate halt of GAMBIT loop requested.") {}
514 
515 
517 
520 
521 
524  SilentShutdownException::SilentShutdownException(const std::string& message) : myWhat(message) {}
525  const char* SilentShutdownException::what() const throw() { return myWhat.c_str(); }
527 
529  SoftShutdownException::SoftShutdownException(const std::string& message) : myWhat(message) {}
530  const char* SoftShutdownException::what() const throw() { return myWhat.c_str(); }
532 
534  HardShutdownException::HardShutdownException(const std::string& message) : myWhat(message) {}
535  const char* HardShutdownException::what() const throw() { return myWhat.c_str(); }
537 
539  MPIShutdownException::MPIShutdownException(const std::string& message) : myWhat(message) {}
540  const char* MPIShutdownException::what() const throw() { return myWhat.c_str(); }
542 
545 
547  void Piped_exceptions::request(std::string origin, std::string message)
548  {
549  #pragma omp critical (GAMBIT_piped_exception)
550  {
551  if(exceptions.size() < maxExceptions)
552  this->exceptions.push_back(description(origin,message));
553  this->flag = true;
554  }
555  }
556 
559  {
560  this->request(desc.first, desc.second);
561  }
562 
564  void Piped_exceptions::check(exception &excep)
565  {
566  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
567  {
568  if (this->flag)
569  {
570  // Raise all exceptions (only the first if they are fatal)
571  for(size_t i= 0; i < std::min(exceptions.size(),maxExceptions); i++)
572  {
573  excep.raise(exceptions.at(i).first, exceptions.at(i).second);
574  }
575  // Reset
576  this->flag = false;
577  exceptions.clear();
578  }
579  }
580  else
581  {
582  #pragma omp critical (GAMBIT_exception)
583  {
584  cerr << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl;
585  cerr << "GAMBIT has exited with fatal exception: Piped_exceptions::check() called inside an OpenMP block." << endl
586  << "Piped exceptions may be requested inside OpenMP blocks, but should only be checked outside the block." << endl;
587  if (this->flag)
588  {
589  cerr << "Exceptions stored: " << endl << endl;
590  for(size_t i= 0; i < std::min(exceptions.size(),maxExceptions); i++)
591  {
592  cerr << exceptions.at(i).second << endl
593  << "\nRaised at: " << exceptions.at(i).first << "." << endl << endl;
594  }
595  }
596  else cerr << "No exceptions stored." << endl;
597  #ifdef WITH_MPI
598  GMPI::Comm().Abort();
599  #else
600  abort();
601  #endif
602  }
603  }
604  }
605 
608  {
609  return this->flag;
610  }
611 
613  bool Piped_exceptions::inquire(std::string message)
614  {
615  if (not this->flag) return false;
616  auto it = std::find_if(exceptions.cbegin(), exceptions.cend(),
617  [&message](std::pair<std::string,std::string> const &e){ return e.second == message; });
618  return it != exceptions.cend();
619  }
620 
623 
626 }
627 
628 
error(const char *, const char *)
ConstructorsConstructor without log tags.
Definition: exceptions.cpp:300
Piped_exceptions piped_errors
Global instance of Piped_exceptions class for errors.
int invalidcode
Integer code used for exceptions.
Definition: exceptions.hpp:214
General small utility macros.
special_exception(const char *)
Constructor.
Definition: exceptions.cpp:363
std::string myMessage
The message passed when this exception is raised.
Definition: exceptions.hpp:224
EXPORT_SYMBOLS error & utils_error()
Utility errors.
std::pair< std::string, std::string > description
Definition: exceptions.hpp:306
LogTags::LogTag_declaration LogTag
Definition: log_tags.hpp:62
Threadsafe exception class declarations.
void request(std::string origin, std::string message)
Request an exception.
Definition: exceptions.cpp:547
#define LOCAL_INFO
Definition: local_info.hpp:34
Function wrapper (functor) base class.
Definition: functors.hpp:87
Piped_exceptions piped_warnings
Global instance of Piped_exceptions class for warnings.
HardShutdownException(const std::string &message)
HardShutdownException member functions.
Definition: exceptions.cpp:534
STL namespace.
virtual const char * what() const
Retrieve the identity of the exception.
Definition: exceptions.cpp:366
SilentShutdownException()
SilentShutdownException member functions.
Definition: exceptions.cpp:523
Logging access header for GAMBIT.
bool inquire()
Check whether any exceptions were requested without handling them.
Definition: exceptions.cpp:607
halt_loop_exception()
Constructor.
Definition: exceptions.cpp:513
std::string message()
Retrieve the message that this exception was raised with.
Definition: exceptions.cpp:374
functor * thrower()
Retrieve pointer to the functor that threw the invalid point exception.
Definition: exceptions.cpp:410
Piped_invalid_point piped_invalid_point
Global instance of piped invalid point class.
Definition: exceptions.cpp:544
virtual const char * what() const
Definition: exceptions.cpp:535
virtual void raise(const std::string &)
Raise the exception, i.e. throw it. Exact override of base method.
Definition: exceptions.cpp:422
functor * myThrower
The functor responsible for throwing this exception.
Definition: exceptions.hpp:235
GAMBIT special exception class. Not logged, meant for always catching.
Definition: exceptions.hpp:194
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
virtual const char * what() const
Definition: exceptions.cpp:525
virtual void raise(const std::string &)
Raise the exception, i.e. throw it.
Definition: exceptions.cpp:385
invalid_point_exception()
Constructor.
Definition: exceptions.cpp:398
Gambit piped invalid point exception class.
Definition: exceptions.hpp:282
A simple C++ wrapper for the MPI C bindings.
void check(exception &excep)
Check whether any exceptions were requested, and raise them.
Definition: exceptions.cpp:564
warning(const char *, const char *)
ConstructorsConstructor without log tags.
Definition: exceptions.cpp:331
void check()
Check whether an exception was requested, and throw it if necessary.
Definition: exceptions.cpp:481
Exception objects required for standalone compilation.
virtual const char * what() const
Definition: exceptions.cpp:530
void set_thrower(functor *)
Set the pointer to the functor that threw the invalid point exception.
Definition: exceptions.cpp:401
void request(std::string message)
Request an exception.
Definition: exceptions.cpp:471
invalid_point_exception & invalid_point()
Invalid point exceptions.
MPIShutdownException(const std::string &message)
MPIShutdownException member functions.
Definition: exceptions.cpp:539
const char * myWhat
What this exception is (for returning with what method).
Definition: exceptions.hpp:219
virtual const char * what() const
Definition: exceptions.cpp:540
SoftShutdownException(const std::string &message)
SoftShutdownException member functions.
Definition: exceptions.cpp:529
TODO: see if we can use this one:
Definition: Analysis.hpp:33
Gambit piped error class.
Definition: exceptions.hpp:303
void abort_here_and_now()
Cause the code to print the exception and abort.
Definition: exceptions.cpp:456