gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-252-gf9a3f78
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  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
425  {
426  #pragma omp critical (GAMBIT_exception)
427  {
428  myMessage = msg;
429  }
430  throw(*this);
431  }
432  else
433  {
434  std::ostringstream full_msg;
435  full_msg << "Sorry, you cannot raise an invalid point exception inside an OpenMP block." << endl
436  << "Please use piped_invalid_point.request() in your block, then check it with " << endl
437  << "piped_invalid_point.check() to raise the exception outside the block." << endl
438  << "Message: " << msg;
439  #pragma omp critical (GAMBIT_exception)
440  {
441  myMessage = full_msg.str();
442  }
443  abort_here_and_now(); // If in an OpenMP parallel block, just abort immediately.
444  }
445  }
446 
449  {
450  #pragma omp critical (GAMBIT_invalid_pt_exception)
451  {
452  cerr << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl;
453  cerr << "An invalid_point exception is fatal inside an OpenMP block. " << endl << what() << endl << message() << endl;
454  #ifdef WITH_MPI
455  GMPI::Comm().Abort();
456  #else
457  abort();
458  #endif
459  }
460  }
461 
463  void Piped_invalid_point::request(std::string message)
464  {
465  #pragma omp critical (GAMBIT_piped_invalid_point)
466  {
467  this->message = message;
468  this->flag = true;
469  }
470  }
471 
474  {
475  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
476  {
477  if (this->flag)
478  {
479  this->flag = false; // Reset...
480  invalid_point().raise(this->message); // ...and throw.
481  }
482  }
483  else
484  {
485  #pragma omp critical (GAMBIT_invalid_point)
486  {
487  cerr << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl;
488  cerr << "GAMBIT has exited with fatal exception: Piped_invalid_point::check() called inside an OpenMP block." << endl
489  << "Piped exceptions may be requested inside OpenMP blocks, but should only be checked outside the block." << endl;
490  if (this->flag)
491  cerr << "Invalid point message requested: " << endl << this->message;
492  else cerr << "No invalid point requested." << endl;
493  #ifdef WITH_MPI
494  GMPI::Comm().Abort();
495  #else
496  abort();
497  #endif
498  }
499  }
500  }
501 
504  SilentShutdownException::SilentShutdownException(const std::string& message) : myWhat(message) {}
505  const char* SilentShutdownException::what() const throw() { return myWhat.c_str(); }
507 
509  SoftShutdownException::SoftShutdownException(const std::string& message) : myWhat(message) {}
510  const char* SoftShutdownException::what() const throw() { return myWhat.c_str(); }
512 
514  HardShutdownException::HardShutdownException(const std::string& message) : myWhat(message) {}
515  const char* HardShutdownException::what() const throw() { return myWhat.c_str(); }
517 
519  MPIShutdownException::MPIShutdownException(const std::string& message) : myWhat(message) {}
520  const char* MPIShutdownException::what() const throw() { return myWhat.c_str(); }
522 
525 
527  void Piped_exceptions::request(std::string origin, std::string message)
528  {
529  #pragma omp critical (GAMBIT_piped_exception)
530  {
531  if(exceptions.size() < maxExceptions)
532  this->exceptions.push_back(description(origin,message));
533  this->flag = true;
534  }
535  }
536 
539  {
540  this->request(desc.first, desc.second);
541  }
542 
544  void Piped_exceptions::check(exception &excep)
545  {
546  if (omp_get_level()==0) // If not in an OpenMP parallel block, throw onwards
547  {
548  if (this->flag)
549  {
550  // Raise all exceptions (only the first if they are fatal)
551  for(size_t i= 0; i < std::min(exceptions.size(),maxExceptions); i++)
552  {
553  excep.raise(exceptions.at(i).first, exceptions.at(i).second);
554  }
555  // Reset
556  this->flag = false;
557  exceptions.clear();
558  }
559  }
560  else
561  {
562  #pragma omp critical (GAMBIT_exception)
563  {
564  cerr << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl;
565  cerr << "GAMBIT has exited with fatal exception: Piped_exceptions::check() called inside an OpenMP block." << endl
566  << "Piped exceptions may be requested inside OpenMP blocks, but should only be checked outside the block." << endl;
567  if (this->flag)
568  {
569  cerr << "Exceptions stored: " << endl << endl;
570  for(size_t i= 0; i < std::min(exceptions.size(),maxExceptions); i++)
571  {
572  cerr << exceptions.at(i).second << endl
573  << "\nRaised at: " << exceptions.at(i).first << "." << endl << endl;
574  }
575  }
576  else cerr << "No exceptions stored." << endl;
577  #ifdef WITH_MPI
578  GMPI::Comm().Abort();
579  #else
580  abort();
581  #endif
582  }
583  }
584  }
585 
588  {
589  return this->flag;
590  }
591 
593  bool Piped_exceptions::inquire(std::string message)
594  {
595  if (not this->flag) return false;
596  auto it = std::find_if(exceptions.cbegin(), exceptions.cend(),
597  [&message](std::pair<std::string,std::string> const &e){ return e.second == message; });
598  return it != exceptions.cend();
599  }
600 
603 
606 }
607 
608 
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.
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:221
EXPORT_SYMBOLS error & utils_error()
Utility errors.
std::pair< std::string, std::string > description
Definition: exceptions.hpp:278
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:527
#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:514
STL namespace.
virtual const char * what() const
Retrieve the identity of the exception.
Definition: exceptions.cpp:366
SilentShutdownException()
SilentShutdownException member functions.
Definition: exceptions.cpp:503
Logging access header for GAMBIT.
bool inquire()
Check whether any exceptions were requested without handling them.
Definition: exceptions.cpp:587
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:524
virtual const char * what() const
Definition: exceptions.cpp:515
virtual void raise(const std::string &)
Raise the exception, i.e. throw it.
Definition: exceptions.cpp:422
functor * myThrower
The functor responsible for throwing this exception.
Definition: exceptions.hpp:232
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:99
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:505
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:254
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:544
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:473
Exception objects required for standalone compilation.
virtual const char * what() const
Definition: exceptions.cpp:510
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:463
invalid_point_exception & invalid_point()
Invalid point exceptions.
MPIShutdownException(const std::string &message)
MPIShutdownException member functions.
Definition: exceptions.cpp:519
const char * myWhat
What this exception is (for returning with what method).
Definition: exceptions.hpp:216
virtual const char * what() const
Definition: exceptions.cpp:520
SoftShutdownException(const std::string &message)
SoftShutdownException member functions.
Definition: exceptions.cpp:509
TODO: see if we can use this one:
Definition: Analysis.hpp:33
Gambit piped error class.
Definition: exceptions.hpp:275
void abort_here_and_now()
Cause the code to print the exception and abort.
Definition: exceptions.cpp:448