debug: don't rely on format for output
debug is relied upon by a great deal of other units so it's very difficult to include other popular headers like format.hpp without triggering cyclic dependencies.
This commit is contained in:
parent
06e29ed136
commit
4116442e40
@ -11,13 +11,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_ALLOC_ARENA_HPP
|
#ifndef CRUFT_UTIL_ALLOC_ARENA_HPP
|
||||||
#define __UTIL_ALLOC_ARENA_HPP
|
#define CRUFT_UTIL_ALLOC_ARENA_HPP
|
||||||
|
|
||||||
#include "../memory/deleter.hpp"
|
#include "../memory/deleter.hpp"
|
||||||
|
#include "../cast.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
167
debug.hpp
167
debug.hpp
@ -14,8 +14,7 @@
|
|||||||
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DEBUG_HPP
|
#pragma once
|
||||||
#define __DEBUG_HPP
|
|
||||||
|
|
||||||
//#include "maths.hpp" // XXX: See notes at the end of file for maths.hpp inclusion
|
//#include "maths.hpp" // XXX: See notes at the end of file for maths.hpp inclusion
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -23,7 +22,8 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <iostream>
|
#include <iosfwd>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -47,6 +47,7 @@
|
|||||||
/// refer to variables which do not always exist, and current compiler
|
/// refer to variables which do not always exist, and current compiler
|
||||||
/// implementations are a little picky here.
|
/// implementations are a little picky here.
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
#include <iostream>
|
||||||
#define DEBUG_ONLY(X) do { X; } while (0)
|
#define DEBUG_ONLY(X) do { X; } while (0)
|
||||||
#else
|
#else
|
||||||
#define DEBUG_ONLY(X) do { ; } while (0)
|
#define DEBUG_ONLY(X) do { ; } while (0)
|
||||||
@ -64,7 +65,11 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define TRACE { \
|
#define TRACE { \
|
||||||
DEBUG_ONLY ( \
|
DEBUG_ONLY ( \
|
||||||
std::clog << "tid: " << std::this_thread::get_id () << "; " << __FILE__ << ":" << __func__ << ":" << __LINE__ << std::endl; \
|
std::cerr << "tid: " << std::this_thread::get_id () \
|
||||||
|
<< "; " << __FILE__ \
|
||||||
|
<< ":" << __func__ \
|
||||||
|
<< ":" << __LINE__ \
|
||||||
|
<< '\n'; \
|
||||||
); \
|
); \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +77,11 @@
|
|||||||
#define WARN(C) do { \
|
#define WARN(C) do { \
|
||||||
DEBUG_ONLY ( \
|
DEBUG_ONLY ( \
|
||||||
if (C) { \
|
if (C) { \
|
||||||
std::cerr << __FILE__ << ":" << __func__ << ":" << __LINE__ << ", " << #C << std::endl; \
|
std::cerr << __FILE__ \
|
||||||
|
<< ":" << __func__ \
|
||||||
|
<< ":" << __LINE__ \
|
||||||
|
<< ", " << #C \
|
||||||
|
<< '\n'; \
|
||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -81,7 +90,7 @@
|
|||||||
#define WARN_RETURN(CONDITION,VALUE) do { \
|
#define WARN_RETURN(CONDITION,VALUE) do { \
|
||||||
if (const auto& __warn_return = (CONDITION); !!__warn_return) { \
|
if (const auto& __warn_return = (CONDITION); !!__warn_return) { \
|
||||||
if constexpr (debug_enabled) { \
|
if constexpr (debug_enabled) { \
|
||||||
std::clog << __FILE__ << ':' \
|
std::cerr << __FILE__ << ':' \
|
||||||
<< __LINE__ << ':' \
|
<< __LINE__ << ':' \
|
||||||
<< __PRETTY_FUNCTION__ << "; " \
|
<< __PRETTY_FUNCTION__ << "; " \
|
||||||
<< #CONDITION << '\n'; \
|
<< #CONDITION << '\n'; \
|
||||||
@ -96,7 +105,7 @@
|
|||||||
#define RETURN_UNLESS(VALUE,CONDITION) do { \
|
#define RETURN_UNLESS(VALUE,CONDITION) do { \
|
||||||
if (const auto &__return_unless = (CONDITION); !__return_unless) { \
|
if (const auto &__return_unless = (CONDITION); !__return_unless) { \
|
||||||
if constexpr (debug_enabled) { \
|
if constexpr (debug_enabled) { \
|
||||||
std::clog << __FILE__ << ':' \
|
std::cerr << __FILE__ << ':' \
|
||||||
<< __LINE__ << ':' \
|
<< __LINE__ << ':' \
|
||||||
<< __PRETTY_FUNCTION__ << "; " \
|
<< __PRETTY_FUNCTION__ << "; " \
|
||||||
<< #CONDITION << '\n'; \
|
<< #CONDITION << '\n'; \
|
||||||
@ -108,14 +117,6 @@
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
#define _CHECK_PANIC(FMT,...) do { \
|
|
||||||
panic ("%s:%s:%i:%s\n" FMT, \
|
|
||||||
PACKAGE, __FILE__, __LINE__, __func__, \
|
|
||||||
__VA_ARGS__); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK(C) do { \
|
#define CHECK(C) do { \
|
||||||
DEBUG_ONLY ( \
|
DEBUG_ONLY ( \
|
||||||
@ -142,11 +143,9 @@
|
|||||||
const auto &__b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (!::util::almost_equal (__a, __b)) { \
|
if (!::util::almost_equal (__a, __b)) { \
|
||||||
_CHECK_PANIC("expected equality\n" \
|
std::cerr << "expected equality\n" \
|
||||||
"__a: %s is %!\n" \
|
"__a: " #A " is " << __a << "\n" \
|
||||||
"__b: %s is %!\n", \
|
"__b: " #B " is " << __b << "\n"; \
|
||||||
#A, __a, \
|
|
||||||
#B, __b); \
|
|
||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -159,11 +158,9 @@
|
|||||||
const auto &__b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a >= __b) { \
|
if (__a >= __b) { \
|
||||||
_CHECK_PANIC("expected less than\n" \
|
std::cerr << "expected less than\n" \
|
||||||
"__a: %s is %!\n" \
|
"__a: " << #A << " is " << __a << "\n" \
|
||||||
"__b: %s is %!\n", \
|
"__b: " << #B << " is " << __b << "\n"; \
|
||||||
#A, __a, \
|
|
||||||
#B, __b); \
|
|
||||||
}; \
|
}; \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -176,11 +173,9 @@
|
|||||||
const auto &__b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a > __b) { \
|
if (__a > __b) { \
|
||||||
_CHECK_PANIC("expected less than or equal\n" \
|
std::cerr << "expected less than or equal\n" \
|
||||||
"__a: %s is %!\n" \
|
"__a: " << #A << " is " << __a << "\n" \
|
||||||
"__b: %s is %!\n", \
|
"__b: " << #B << " is " << __b << "\n"; \
|
||||||
#A, __a, \
|
|
||||||
#B, __b); \
|
|
||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -193,11 +188,9 @@
|
|||||||
const auto &__b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a <= __b) { \
|
if (__a <= __b) { \
|
||||||
_CHECK_PANIC ("expected greater than\n" \
|
std::cerr << "expected greater than\n" \
|
||||||
"__a: %s is %!\n" \
|
"__a: " << #A << " is " << __a << "\n" \
|
||||||
"__b: %s is %!\n", \
|
"__b: " << #B << " is " << __b << "\n"; \
|
||||||
#A, __a, \
|
|
||||||
#B, __b); \
|
|
||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -210,11 +203,9 @@
|
|||||||
const auto &__b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a < __b) { \
|
if (__a < __b) { \
|
||||||
_CHECK_PANIC ("expected greater or equal\n" \
|
std::cerr << "expected greater or equal\n" \
|
||||||
"__a: %s is %!\n" \
|
"__a: " << #A << " is " << __a << "\n" \
|
||||||
"__b: %s is %!\n", \
|
"__b: " << #B << " is " << __b << "\n"; \
|
||||||
#A, __a, \
|
|
||||||
#B, __b); \
|
|
||||||
}; \
|
}; \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -228,13 +219,10 @@
|
|||||||
const auto &__h = (H); \
|
const auto &__h = (H); \
|
||||||
\
|
\
|
||||||
if (__v < __l || __v > __h) { \
|
if (__v < __l || __v > __h) { \
|
||||||
_CHECK_PANIC ("expected limit\n" \
|
std::cerr << "expected limit\n" \
|
||||||
"__l: %s is %!\n" \
|
"__l: " << #L << " is " << +__l << "\n" \
|
||||||
"__h: %s is %!\n" \
|
"__h: " << #H << " is " << +__h << "\n" \
|
||||||
"__v: %s is %!\n", \
|
"__v: " << #V << " is " << +__v << "\n"; \
|
||||||
#L, __l, \
|
|
||||||
#H, __h, \
|
|
||||||
#V, __v); \
|
|
||||||
}; \
|
}; \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -246,11 +234,9 @@
|
|||||||
const auto &__b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (::util::almost_equal (__a, __b)) { \
|
if (::util::almost_equal (__a, __b)) { \
|
||||||
_CHECK_PANIC ("expected inequality\n" \
|
std::cerr << "expected inequality\n" \
|
||||||
"__a: %s is %!\n" \
|
"__a: " << #A << " is " << __a << "\n" \
|
||||||
"__b: %s is %!\n", \
|
"__b: " << #B << " is " << __b << "\n"; \
|
||||||
#A, __a, \
|
|
||||||
#B, __b); \
|
|
||||||
}; \
|
}; \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -262,9 +248,8 @@
|
|||||||
const auto &__a = (A); \
|
const auto &__a = (A); \
|
||||||
\
|
\
|
||||||
if (!::util::almost_zero (__a)) { \
|
if (!::util::almost_zero (__a)) { \
|
||||||
_CHECK_PANIC ("expected zero\n" \
|
std::cerr << "expected zero\n" \
|
||||||
"__a: %s is %!\n" \
|
"__a: " << #A << " is " << __a << "\n"; \
|
||||||
#A, __a); \
|
|
||||||
}; \
|
}; \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -276,9 +261,8 @@
|
|||||||
const auto &__a = (A); \
|
const auto &__a = (A); \
|
||||||
\
|
\
|
||||||
if (::util::exactly_zero (__a)) \
|
if (::util::exactly_zero (__a)) \
|
||||||
_CHECK_PANIC ("expected non-zero\n" \
|
std::cerr << "expected non-zero\n" \
|
||||||
"__a: %s is %!", \
|
"__a: " << #A << " is " << __a << '\n'; \
|
||||||
#A, __a); \
|
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -290,11 +274,9 @@
|
|||||||
const auto &__check_mod_m = (M); \
|
const auto &__check_mod_m = (M); \
|
||||||
\
|
\
|
||||||
if (!::util::exactly_zero (__check_mod_v % __check_mod_m)) \
|
if (!::util::exactly_zero (__check_mod_v % __check_mod_m)) \
|
||||||
_CHECK_PANIC ("expected zero modulus\n" \
|
std::cerr << "expected zero modulus\n" \
|
||||||
"__v: %s is %!\n" \
|
"__v: " << #V << " is " << __check_mod_v << "\n" \
|
||||||
"__m: %s is %!", \
|
"__m: " << #M << " is " << __check_mod_m << "\n"; \
|
||||||
#V, __check_mod_v, \
|
|
||||||
#M, __check_mod_m); \
|
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -308,9 +290,8 @@
|
|||||||
if (std::find (std::cbegin (__e), \
|
if (std::find (std::cbegin (__e), \
|
||||||
std::cend (__e), \
|
std::cend (__e), \
|
||||||
__c) == std::end (__e)) { \
|
__c) == std::end (__e)) { \
|
||||||
_CHECK_PANIC("expect enum\n" \
|
std::cerr << "expect enum\n" \
|
||||||
"__c: %s is %!", \
|
"__c: " << #C << " is " << __c << '\n'; \
|
||||||
#C, __c); \
|
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
@ -322,9 +303,8 @@
|
|||||||
#define CHECK_FINITE(V) do { \
|
#define CHECK_FINITE(V) do { \
|
||||||
const auto &__v = (V); \
|
const auto &__v = (V); \
|
||||||
if (!std::isfinite (__v)) { \
|
if (!std::isfinite (__v)) { \
|
||||||
_CHECK_PANIC ("expected finite value\n" \
|
std::cerr << "expected finite value\n" \
|
||||||
"__v: %! is %!", \
|
"__v: " << #V << " is " << __v << '\n'; \
|
||||||
#V, __v); \
|
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
@ -345,7 +325,7 @@
|
|||||||
{ caught = true; } \
|
{ caught = true; } \
|
||||||
\
|
\
|
||||||
if (!caught) \
|
if (!caught) \
|
||||||
_CHECK_PANIC ("expected exception: %s", #E); \
|
std::cerr << "expected exception: " << #E << '\n' \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -356,11 +336,9 @@
|
|||||||
try { \
|
try { \
|
||||||
C; \
|
C; \
|
||||||
} catch (const std::exception &e) { \
|
} catch (const std::exception &e) { \
|
||||||
_CHECK_PANIC ("unexpected exception: %s", \
|
std::cerr << "unexpected exception: " << e.what () << '\n'; \
|
||||||
e.what ()); \
|
|
||||||
} catch (...) { \
|
} catch (...) { \
|
||||||
_CHECK_PANIC ("unexpected exception: %s", \
|
std::cerr << "unexpected exception: unknown\n"; \
|
||||||
"unknown"); \
|
|
||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -434,23 +412,14 @@ void breakpoint (void);
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#include "log.hpp"
|
|
||||||
#include "backtrace.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace util::debug::detail {
|
namespace util::debug::detail {
|
||||||
void panic [[noreturn]] (const char *msg);
|
void
|
||||||
|
panic [[noreturn]] (const char *msg);
|
||||||
|
|
||||||
template <typename ...Args, size_t N>
|
|
||||||
void panic [[noreturn]] (const char (&fmt)[N], const Args& ...args)
|
|
||||||
{
|
|
||||||
LOG_EMERGENCY (fmt, args...);
|
|
||||||
LOG_EMERGENCY ("%!", ::debug::backtrace ());
|
|
||||||
breakpoint ();
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void not_implemented [[noreturn]] (const char *msg);
|
void not_implemented [[noreturn]] (const char *msg);
|
||||||
|
|
||||||
|
|
||||||
void unreachable [[noreturn]] (const char *msg);
|
void unreachable [[noreturn]] (const char *msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,11 +434,10 @@ panic [[noreturn]] (const char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename ...Args, size_t N>
|
inline void
|
||||||
constexpr void
|
panic [[noreturn]] (const std::string &msg)
|
||||||
panic [[noreturn]] (const char (&fmt)[N], const Args&... args)
|
|
||||||
{
|
{
|
||||||
util::debug::detail::panic (fmt, args...);
|
panic (msg.c_str ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -530,11 +498,23 @@ unreachable [[noreturn]] (void)
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
/// report a fatal error induced by an unhandled value, especially in switch
|
/// report a fatal error induced by an unhandled value, especially in switch
|
||||||
/// statements. will almost invariably abort the application.
|
/// statements. will almost invariably abort the application.
|
||||||
|
namespace util::debug::detail {
|
||||||
|
template <typename T>
|
||||||
|
void
|
||||||
|
unhandled [[noreturn]] (T &&t) noexcept
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "unhandled value: " << t << '\n';
|
||||||
|
::panic (os.str ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr void
|
constexpr void
|
||||||
unhandled [[noreturn]] (T &&t) noexcept
|
unhandled [[noreturn]] (T &&t) noexcept
|
||||||
{
|
{
|
||||||
panic ("unhandled value %!", std::forward<T> (t));
|
util::debug::detail::unhandled (std::forward<T> (t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -648,6 +628,3 @@ namespace util::debug {
|
|||||||
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
|
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
|
||||||
// after we define the CHECK_ macros so the preprocessor can resolve them.
|
// after we define the CHECK_ macros so the preprocessor can resolve them.
|
||||||
#include "maths.hpp"
|
#include "maths.hpp"
|
||||||
|
|
||||||
|
|
||||||
#endif // __DEBUG_HPP
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
#include "maths.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
Loading…
Reference in New Issue
Block a user