Update cpptrace exceptions to defer trace generation to the callsite with a default argument
This commit is contained in:
parent
2f7f5107a5
commit
ab2d440a00
29
README.md
29
README.md
@ -320,13 +320,13 @@ interface or type system but this seems to be the best way to do this.
|
||||
```cpp
|
||||
namespace cpptrace {
|
||||
class lazy_exception : public exception {
|
||||
mutable detail::lazy_trace_holder trace_holder; // basically std::variant<raw_trace, stacktrace>, more docs later
|
||||
// lazy_trace_holder is basically a std::variant<raw_trace, stacktrace>, more docs later
|
||||
mutable detail::lazy_trace_holder trace_holder;
|
||||
mutable std::string what_string;
|
||||
protected:
|
||||
explicit lazy_exception(std::size_t skip, std::size_t max_depth) noexcept;
|
||||
explicit lazy_exception(std::size_t skip) noexcept;
|
||||
public:
|
||||
explicit lazy_exception() noexcept : lazy_exception(1) {}
|
||||
explicit lazy_exception(
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept : trace_holder(std::move(trace)) {}
|
||||
const char* what() const noexcept override;
|
||||
const char* message() const noexcept override;
|
||||
const stacktrace& trace() const noexcept override;
|
||||
@ -341,19 +341,22 @@ well as a number of traced exception classes resembling `<stdexcept>`:
|
||||
|
||||
```cpp
|
||||
namespace cpptrace {
|
||||
class CPPTRACE_EXPORT exception_with_message : public lazy_exception {
|
||||
class exception_with_message : public lazy_exception {
|
||||
mutable std::string user_message;
|
||||
protected:
|
||||
explicit exception_with_message(std::string&& message_arg, std::size_t skip) noexcept;
|
||||
explicit exception_with_message(std::string&& message_arg, std::size_t skip, std::size_t max_depth) noexcept;
|
||||
public:
|
||||
explicit exception_with_message(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
|
||||
explicit exception_with_message(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept : lazy_exception(std::move(trace)), user_message(std::move(message_arg)) {}
|
||||
const char* message() const noexcept override;
|
||||
};
|
||||
|
||||
// All stdexcept errors have analogs here. Same constructor as exception_with_message.
|
||||
// All stdexcept errors have analogs here. All have the constructor:
|
||||
// explicit the_error(
|
||||
// std::string&& message_arg,
|
||||
// raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
// ) noexcept
|
||||
// : exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
class logic_error : public exception_with_message { ... };
|
||||
class domain_error : public exception_with_message { ... };
|
||||
class invalid_argument : public exception_with_message { ... };
|
||||
|
||||
@ -289,6 +289,9 @@ namespace cpptrace {
|
||||
private:
|
||||
void clear();
|
||||
};
|
||||
|
||||
CPPTRACE_EXPORT raw_trace get_raw_trace_and_absorb(std::size_t skip, std::size_t max_depth) noexcept;
|
||||
CPPTRACE_EXPORT raw_trace get_raw_trace_and_absorb(std::size_t skip = 0) noexcept;
|
||||
}
|
||||
|
||||
// Interface for a traced exception object
|
||||
@ -301,17 +304,14 @@ namespace cpptrace {
|
||||
|
||||
// Cpptrace traced exception object
|
||||
// I hate to have to expose anything about implementation detail but the idea here is that
|
||||
// TODO: CPPTRACE_FORCE_NO_INLINE annotations
|
||||
class CPPTRACE_EXPORT lazy_exception : public exception {
|
||||
mutable detail::lazy_trace_holder trace_holder;
|
||||
mutable std::string what_string;
|
||||
|
||||
protected:
|
||||
explicit lazy_exception(std::size_t skip, std::size_t max_depth) noexcept;
|
||||
explicit lazy_exception(std::size_t skip) noexcept : lazy_exception(skip + 1, SIZE_MAX) {}
|
||||
|
||||
public:
|
||||
explicit lazy_exception() noexcept : lazy_exception(1) {}
|
||||
explicit lazy_exception(
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept : trace_holder(std::move(trace)) {}
|
||||
// std::exception
|
||||
const char* what() const noexcept override;
|
||||
// cpptrace::exception
|
||||
@ -322,87 +322,105 @@ namespace cpptrace {
|
||||
class CPPTRACE_EXPORT exception_with_message : public lazy_exception {
|
||||
mutable std::string user_message;
|
||||
|
||||
protected:
|
||||
explicit exception_with_message(
|
||||
std::string&& message_arg,
|
||||
std::size_t skip
|
||||
) noexcept : lazy_exception(skip + 1), user_message(std::move(message_arg)) {}
|
||||
|
||||
explicit exception_with_message(
|
||||
std::string&& message_arg,
|
||||
std::size_t skip,
|
||||
std::size_t max_depth
|
||||
) noexcept : lazy_exception(skip + 1, max_depth), user_message(std::move(message_arg)) {}
|
||||
|
||||
public:
|
||||
explicit exception_with_message(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit exception_with_message(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept : lazy_exception(std::move(trace)), user_message(std::move(message_arg)) {}
|
||||
|
||||
const char* message() const noexcept override;
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT logic_error : public exception_with_message {
|
||||
public:
|
||||
explicit logic_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit logic_error(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT domain_error : public exception_with_message {
|
||||
public:
|
||||
explicit domain_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit domain_error(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT invalid_argument : public exception_with_message {
|
||||
public:
|
||||
explicit invalid_argument(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit invalid_argument(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT length_error : public exception_with_message {
|
||||
public:
|
||||
explicit length_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit length_error(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT out_of_range : public exception_with_message {
|
||||
public:
|
||||
explicit out_of_range(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit out_of_range(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT runtime_error : public exception_with_message {
|
||||
public:
|
||||
explicit runtime_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit runtime_error(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT range_error : public exception_with_message {
|
||||
public:
|
||||
explicit range_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit range_error(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT overflow_error : public exception_with_message {
|
||||
public:
|
||||
explicit overflow_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit overflow_error(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT underflow_error : public exception_with_message {
|
||||
public:
|
||||
explicit underflow_error(std::string&& message_arg) noexcept
|
||||
: exception_with_message(std::move(message_arg), 1) {}
|
||||
explicit underflow_error(
|
||||
std::string&& message_arg,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: exception_with_message(std::move(message_arg), std::move(trace)) {}
|
||||
};
|
||||
|
||||
class CPPTRACE_EXPORT nested_exception : public lazy_exception {
|
||||
std::exception_ptr ptr;
|
||||
mutable std::string message_value;
|
||||
public:
|
||||
explicit nested_exception(std::exception_ptr exception_ptr) noexcept
|
||||
: lazy_exception(1), ptr(exception_ptr) {}
|
||||
explicit nested_exception(std::exception_ptr exception_ptr, std::size_t skip) noexcept
|
||||
: lazy_exception(skip + 1), ptr(exception_ptr) {}
|
||||
explicit nested_exception(
|
||||
std::exception_ptr exception_ptr,
|
||||
raw_trace&& trace = detail::get_raw_trace_and_absorb()
|
||||
) noexcept
|
||||
: lazy_exception(std::move(trace)), ptr(exception_ptr) {}
|
||||
|
||||
const char* message() const noexcept override;
|
||||
std::exception_ptr nested_ptr() const noexcept;
|
||||
|
||||
@ -459,6 +459,11 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
raw_trace get_raw_trace_and_absorb(std::size_t skip) noexcept {
|
||||
return get_raw_trace_and_absorb(skip + 1, SIZE_MAX);
|
||||
}
|
||||
|
||||
lazy_trace_holder::lazy_trace_holder(const lazy_trace_holder& other) : resolved(other.resolved) {
|
||||
if(other.resolved) {
|
||||
new (&resolved_trace) stacktrace(other.resolved_trace);
|
||||
@ -539,9 +544,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_exception::lazy_exception(std::size_t skip, std::size_t max_depth) noexcept
|
||||
: trace_holder(detail::get_raw_trace_and_absorb(skip + 1, max_depth)) {}
|
||||
|
||||
const char* lazy_exception::what() const noexcept {
|
||||
if(what_string.empty()) {
|
||||
what_string = message() + std::string(":\n") + trace_holder.get_resolved_trace().to_string();
|
||||
@ -585,7 +587,7 @@ namespace cpptrace {
|
||||
} catch(cpptrace::exception&) {
|
||||
throw; // already a cpptrace::exception
|
||||
} catch(...) {
|
||||
throw nested_exception(std::current_exception(), skip + 1);
|
||||
throw nested_exception(std::current_exception(), detail::get_raw_trace_and_absorb(skip + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user