#include <xbt/ex.h>
+/** (Deprecated) Generic exception
+ *
+ * An error is defined by a category and a value within that category.
+ *
+ * This used to be a structure for C exceptions but it has been retrofitted
+ * as a C++ exception and some of its data has been moved in the
+ * WithContextException base class. We should deprecate it and replace it
+ * with either C++ different exceptions or `std::system_error` which already
+ * provides this (category + error code) logic.
+ */
struct XBT_PUBLIC() xbt_ex :
public std::runtime_error,
public simgrid::xbt::WithContextException {
public:
- xbt_ex() : std::runtime_error("") {}
- xbt_ex(const char* message) : std::runtime_error(message) {}
+
+ xbt_ex() :
+ std::runtime_error("")
+ {}
+
+ /**
+ *
+ * @param throwpoint Throw point (use XBT_THROW_POINT)
+ * @param message Exception message
+ */
+ xbt_ex(simgrid::xbt::ThrowPoint throwpoint, const char* message) :
+ std::runtime_error(message),
+ simgrid::xbt::WithContextException(throwpoint, simgrid::xbt::backtrace())
+ {}
+
~xbt_ex() override;
- xbt_errcat_t category; /**< category like HTTP (what went wrong) */
- int value; /**< like errno (why did it went wrong) */
- const char *file; /**< Thrown point */
- int line; /**< Thrown point */
- const char *func; /**< Thrown point */
+ /** Category (what went wrong) */
+ xbt_errcat_t category;
+
+ /** Why did it went wrong */
+ int value;
+
};
#endif
typedef std::vector<xbt_backtrace_location_t> Backtrace;
+struct ThrowPoint {
+ ThrowPoint() {}
+ ThrowPoint(const char* file, int line, const char* function) :
+ file(file), line(line), function(function) {}
+ const char* file = nullptr;
+ int line = 0;
+ const char* function = nullptr;
+};
+
/** A polymorphic mixin class for adding context to an exception */
XBT_PUBLIC_CLASS WithContextException {
public:
procname_(xbt_procname()),
pid_(xbt_getpid())
{}
+ WithContextException(ThrowPoint throwpoint, Backtrace bt) :
+ backtrace_(std::move(bt)),
+ procname_(xbt_procname()),
+ pid_(xbt_getpid()),
+ throwpoint_(throwpoint)
+ {}
virtual ~WithContextException();
Backtrace const& backtrace() const
{
}
int pid() const { return pid_; }
std::string const& processName() const { return procname_; }
+ ThrowPoint& throwPoint() { return throwpoint_; }
private:
Backtrace backtrace_;
std::string procname_; /**< Name of the process who thrown this */
int pid_; /**< PID of the process who thrown this */
+ ThrowPoint throwpoint_;
};
/** Internal class used to mixin the two classes */
class WithContext : public E, public WithContextException
{
public:
- WithContext(E exception)
- : E(std::move(exception)) {}
- WithContext(E exception, Backtrace backtrace)
- : E(std::move(exception)), WithContextException(std::move(backtrace)) {}
- WithContext(E exception, WithContextException context)
- : E(std::move(exception)), WithContextException(std::move(context)) {}
+ WithContext(E exception) :
+ E(std::move(exception)) {}
+ WithContext(E exception, ThrowPoint throwpoint, Backtrace backtrace) :
+ E(std::move(exception)),
+ WithContextException(throwpoint, std::move(backtrace)) {}
+ WithContext(E exception, Backtrace backtrace) :
+ E(std::move(exception)),
+ WithContextException(std::move(backtrace)) {}
+ WithContext(E exception, WithContextException context) :
+ E(std::move(exception)),
+ WithContextException(std::move(context)) {}
~WithContext() override {}
};
// Thanks to the default argument, we are taking the backtrace in the caller:
Backtrace backtrace = simgrid::xbt::backtrace())
{
- throw WithContext<E>(std::move(exception), std::move(backtrace));
+ throw WithContext<E>(std::move(exception), std::move(backtrace));
+}
+
+template<class E>
+[[noreturn]] inline
+typename std::enable_if< !std::is_base_of<WithContextException,E>::value >::type
+throwWithContext(
+ E exception,
+ ThrowPoint throwpoint,
+ // Thanks to the default argument, we are taking the backtrace in the caller:
+ Backtrace backtrace = simgrid::xbt::backtrace())
+{
+ throw WithContext<E>(std::move(exception), throwpoint, std::move(backtrace));
}
+#define XBT_THROW_POINT ::simgrid::xbt::ThrowPoint(__FILE__, __LINE__, __func__)
+#define XBT_THROW(e) \
+ ::simgrid::xbt::throwWithContext(std::move(e), XBT_THROW_POINT)
+
}
}