Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[xbt] Move throwpoint out of xbt_ex in WithContextException
[simgrid.git] / include / xbt / exception.hpp
1 /* Copyright (c) 2005-2016. The SimGrid Team.All rights reserved. */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #ifndef SIMGRID_XBT_EXCEPTION_HPP
7 #define SIMGRID_XBT_EXCEPTION_HPP
8
9 #include <string>
10 #include <type_traits>
11 #include <vector>
12
13 #include <xbt/base.h>
14 #include <xbt/backtrace.h>
15 #include <xbt/backtrace.hpp>
16 #include <xbt/log.h>
17 #include <xbt/misc.h>  // xbt_procname
18 #include <xbt/virtu.h> // xbt_getpid
19
20 namespace simgrid {
21 namespace xbt {
22
23 typedef std::vector<xbt_backtrace_location_t> Backtrace;
24
25 struct ThrowPoint {
26   ThrowPoint() {}
27   ThrowPoint(const char* file, int line, const char* function) :
28     file(file), line(line), function(function) {}
29   const char* file = nullptr;
30   int line = 0;
31   const char* function = nullptr;
32 };
33
34 /** A polymorphic mixin class for adding context to an exception */
35 XBT_PUBLIC_CLASS WithContextException {
36 public:
37   WithContextException() :
38     backtrace_(simgrid::xbt::backtrace()),
39     procname_(xbt_procname()),
40     pid_(xbt_getpid())
41   {}
42   WithContextException(Backtrace bt) :
43     backtrace_(std::move(bt)),
44     procname_(xbt_procname()),
45     pid_(xbt_getpid())
46   {}
47   WithContextException(ThrowPoint throwpoint, Backtrace bt) :
48     backtrace_(std::move(bt)),
49     procname_(xbt_procname()),
50     pid_(xbt_getpid()),
51     throwpoint_(throwpoint)
52   {}
53   virtual ~WithContextException();
54   Backtrace const& backtrace() const
55   {
56     return backtrace_;
57   }
58   int pid() const { return pid_; }
59   std::string const& processName() const { return procname_; }
60   ThrowPoint& throwPoint() { return throwpoint_; }
61 private:
62   Backtrace backtrace_;
63   std::string procname_; /**< Name of the process who thrown this */
64   int pid_;              /**< PID of the process who thrown this */
65   ThrowPoint throwpoint_;
66 };
67
68 /** Internal class used to mixin the two classes */
69 template<class E>
70 class WithContext : public E, public WithContextException
71 {
72 public:
73   WithContext(E exception) :
74     E(std::move(exception)) {}
75   WithContext(E exception, ThrowPoint throwpoint, Backtrace backtrace) :
76     E(std::move(exception)),
77     WithContextException(throwpoint, std::move(backtrace)) {}
78   WithContext(E exception, Backtrace backtrace) :
79     E(std::move(exception)),
80     WithContextException(std::move(backtrace)) {}
81   WithContext(E exception, WithContextException context) :
82     E(std::move(exception)),
83     WithContextException(std::move(context)) {}
84   ~WithContext() override {}
85 };
86
87 /** Throw a given exception a context
88  *
89  *  @param exception exception to throw
90  *  @param backtrace backtrace to attach
91  */
92 template<class E>
93 [[noreturn]] inline
94 typename std::enable_if< !std::is_base_of<WithContextException,E>::value >::type
95 throwWithContext(
96   E exception,
97   // Thanks to the default argument, we are taking the backtrace in the caller:
98   Backtrace backtrace = simgrid::xbt::backtrace())
99 {
100   throw WithContext<E>(std::move(exception), std::move(backtrace));
101 }
102
103 template<class E>
104 [[noreturn]] inline
105 typename std::enable_if< !std::is_base_of<WithContextException,E>::value >::type
106 throwWithContext(
107   E exception,
108   ThrowPoint throwpoint,
109   // Thanks to the default argument, we are taking the backtrace in the caller:
110   Backtrace backtrace = simgrid::xbt::backtrace())
111 {
112   throw WithContext<E>(std::move(exception), throwpoint, std::move(backtrace));
113 }
114
115 #define XBT_THROW_POINT ::simgrid::xbt::ThrowPoint(__FILE__, __LINE__, __func__)
116 #define XBT_THROW(e) \
117   ::simgrid::xbt::throwWithContext(std::move(e), XBT_THROW_POINT)
118
119 }
120 }
121
122 #endif