From a764d45cfb438cc9f15cf47ce586c02ff2c65d0f Mon Sep 17 00:00:00 2001 From: tqchen Date: Thu, 16 Mar 2017 10:16:23 -0700 Subject: [PATCH] sync dmlc headers --- include/dmlc/base.h | 48 ++++++++++++++++++---- include/dmlc/io.h | 7 +++- include/dmlc/logging.h | 93 +++++++++++++++++++++++++++++++++--------- include/rabit/rabit.h | 8 +++- 4 files changed, 126 insertions(+), 30 deletions(-) diff --git a/include/dmlc/base.h b/include/dmlc/base.h index 9eca4135f..085ca610e 100644 --- a/include/dmlc/base.h +++ b/include/dmlc/base.h @@ -37,6 +37,14 @@ #define DMLC_LOG_CUSTOMIZE 0 #endif +/*! + * \brief Wheter to print stack trace for fatal error, + * enabled on linux when using gcc. + */ +#if (!defined(DMLC_LOG_STACK_TRACE) && defined(__GNUC__) && !defined(__MINGW32__)) +#define DMLC_LOG_STACK_TRACE 1 +#endif + /*! \brief whether compile with hdfs support */ #ifndef DMLC_USE_HDFS #define DMLC_USE_HDFS 0 @@ -54,13 +62,39 @@ /*! \brief whether or not use c++11 support */ #ifndef DMLC_USE_CXX11 -#define DMLC_USE_CXX11 (defined(__GXX_EXPERIMENTAL_CXX0X__) ||\ - __cplusplus >= 201103L || defined(_MSC_VER)) +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_MSC_VER) +#define DMLC_USE_CXX11 1 +#else +#define DMLC_USE_CXX11 (__cplusplus >= 201103L) +#endif #endif /*! \brief strict CXX11 support */ #ifndef DMLC_STRICT_CXX11 -#define DMLC_STRICT_CXX11 (__cplusplus >= 201103L || defined(_MSC_VER)) +#if defined(_MSC_VER) +#define DMLC_STRICT_CXX11 1 +#else +#define DMLC_STRICT_CXX11 (__cplusplus >= 201103L) +#endif +#endif + +/*! \brief Whether cxx11 thread local is supported */ +#ifndef DMLC_CXX11_THREAD_LOCAL +#if defined(_MSC_VER) +#if (_MSC_VER >= 1900) +#define DMLC_CXX11_THREAD_LOCAL 1 +#else +#define DMLC_CXX11_THREAD_LOCAL 0 +#endif +#else +#define DMLC_CXX11_THREAD_LOCAL (__cplusplus >= 201103L) +#endif +#endif + + +/*! \brief whether RTTI is enabled */ +#ifndef DMLC_ENABLE_RTTI +#define DMLC_ENABLE_RTTI 1 #endif /// check if g++ is before 4.6 @@ -85,7 +119,7 @@ /*! \brief whether enable regex support, actually need g++-4.9 or higher*/ #ifndef DMLC_USE_REGEX -#define DMLC_USE_REGEX (__cplusplus >= 201103L || defined(_MSC_VER)) +#define DMLC_USE_REGEX DMLC_STRICT_CXX11 #endif /*! \brief helper macro to supress unused warning */ @@ -201,7 +235,7 @@ inline T *BeginPtr(std::vector &vec) { // NOLINT(*) } } /*! - * \brief get the beginning address of a vector + * \brief get the beginning address of a const vector * \param vec input vector * \return beginning address of a vector */ @@ -214,7 +248,7 @@ inline const T *BeginPtr(const std::vector &vec) { } } /*! - * \brief get the beginning address of a vector + * \brief get the beginning address of a string * \param str input string * \return beginning address of a string */ @@ -223,7 +257,7 @@ inline char* BeginPtr(std::string &str) { // NOLINT(*) return &str[0]; } /*! - * \brief get the beginning address of a vector + * \brief get the beginning address of a const string * \param str input string * \return beginning address of a string */ diff --git a/include/dmlc/io.h b/include/dmlc/io.h index 31aed37e1..3c416038d 100644 --- a/include/dmlc/io.h +++ b/include/dmlc/io.h @@ -11,6 +11,7 @@ #include #include #include +#include "./logging.h" // include uint64_t only to make io standalone #ifdef _MSC_VER @@ -149,6 +150,8 @@ class InputSplit { * \param chunk_size the chunk size */ virtual void HintChunkSize(size_t chunk_size) {} + /*! \brief get the total size of the InputSplit */ + virtual size_t GetTotalSize(void) = 0; /*! \brief reset the position of InputSplit to beginning */ virtual void BeforeFirst(void) = 0; /*! @@ -243,7 +246,7 @@ class ostream : public std::basic_ostream { this->set_stream(stream); } // explictly synchronize the buffer - virtual ~ostream() { + virtual ~ostream() DMLC_NO_EXCEPTION { buf_.pubsync(); } /*! @@ -313,7 +316,7 @@ class istream : public std::basic_istream { : std::basic_istream(NULL), buf_(buffer_size) { this->set_stream(stream); } - virtual ~istream() {} + virtual ~istream() DMLC_NO_EXCEPTION {} /*! * \brief set internal stream to be stream, reset states * \param stream new stream as output diff --git a/include/dmlc/logging.h b/include/dmlc/logging.h index 0fd6996d1..69d0d36df 100644 --- a/include/dmlc/logging.h +++ b/include/dmlc/logging.h @@ -14,6 +14,10 @@ #include #include "./base.h" +#if DMLC_LOG_STACK_TRACE +#include +#endif + namespace dmlc { /*! * \brief exception class that will be thrown by @@ -28,16 +32,6 @@ struct Error : public std::runtime_error { }; } // namespace dmlc -#if defined(_MSC_VER) && _MSC_VER < 1900 -#define noexcept(a) -#endif - -#if DMLC_USE_CXX11 -#define DMLC_THROW_EXCEPTION noexcept(false) -#else -#define DMLC_THROW_EXCEPTION -#endif - #if DMLC_USE_GLOG #include @@ -63,21 +57,54 @@ inline void InitLogging(const char* argv0) { #endif namespace dmlc { -inline void InitLogging(const char* argv0) { +inline void InitLogging(const char*) { // DO NOTHING } +class LogCheckError { + public: + LogCheckError() : str(nullptr) {} + explicit LogCheckError(const std::string& str_) : str(new std::string(str_)) {} + ~LogCheckError() { if (str != nullptr) delete str; } + operator bool() {return str != nullptr; } + std::string* str; +}; + +#define DEFINE_CHECK_FUNC(name, op) \ + template \ + inline LogCheckError LogCheck##name(const X& x, const Y& y) { \ + if (x op y) return LogCheckError(); \ + std::ostringstream os; \ + os << " (" << x << " vs. " << y << ") "; /* CHECK_XX(x, y) requires x and y can be serialized to string. Use CHECK(x OP y) otherwise. NOLINT(*) */ \ + return LogCheckError(os.str()); \ + } \ + inline LogCheckError LogCheck##name(int x, int y) { \ + return LogCheck##name(x, y); \ + } + +#define CHECK_BINARY_OP(name, op, x, y) \ + if (dmlc::LogCheckError _check_err = dmlc::LogCheck##name(x, y)) \ + dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << "Check failed: " << #x " " #op " " #y << *(_check_err.str) + +DEFINE_CHECK_FUNC(_LT, <) +DEFINE_CHECK_FUNC(_GT, >) +DEFINE_CHECK_FUNC(_LE, <=) +DEFINE_CHECK_FUNC(_GE, >=) +DEFINE_CHECK_FUNC(_EQ, ==) +DEFINE_CHECK_FUNC(_NE, !=) + // Always-on checking #define CHECK(x) \ if (!(x)) \ - dmlc::LogMessageFatal(__FILE__, __LINE__).stream() << "Check " \ - "failed: " #x << ' ' -#define CHECK_LT(x, y) CHECK((x) < (y)) -#define CHECK_GT(x, y) CHECK((x) > (y)) -#define CHECK_LE(x, y) CHECK((x) <= (y)) -#define CHECK_GE(x, y) CHECK((x) >= (y)) -#define CHECK_EQ(x, y) CHECK((x) == (y)) -#define CHECK_NE(x, y) CHECK((x) != (y)) + dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << "Check failed: " #x << ' ' +#define CHECK_LT(x, y) CHECK_BINARY_OP(_LT, <, x, y) +#define CHECK_GT(x, y) CHECK_BINARY_OP(_GT, >, x, y) +#define CHECK_LE(x, y) CHECK_BINARY_OP(_LE, <=, x, y) +#define CHECK_GE(x, y) CHECK_BINARY_OP(_GE, >=, x, y) +#define CHECK_EQ(x, y) CHECK_BINARY_OP(_EQ, ==, x, y) +#define CHECK_NE(x, y) CHECK_BINARY_OP(_NE, !=, x, y) #define CHECK_NOTNULL(x) \ ((x) == NULL ? dmlc::LogMessageFatal(__FILE__, __LINE__).stream() << "Check notnull: " #x << ' ', (x) : (x)) // NOLINT(*) // Debug-only checking. @@ -221,6 +248,20 @@ class LogMessageFatal : public LogMessage { public: LogMessageFatal(const char* file, int line) : LogMessage(file, line) {} ~LogMessageFatal() { +#if DMLC_LOG_STACK_TRACE + const int MAX_STACK_SIZE = 10; + void *stack[MAX_STACK_SIZE]; + + int nframes = backtrace(stack, MAX_STACK_SIZE); + log_stream_ << "\n\n" << "Stack trace returned " << nframes << " entries:\n"; + char **msgs = backtrace_symbols(stack, nframes); + if (msgs != nullptr) { + for (int i = 0; i < nframes; ++i) { + log_stream_ << "[bt] (" << i << ") " << msgs[i] << "\n"; + } + } +#endif + log_stream_ << "\n"; abort(); } @@ -238,6 +279,20 @@ class LogMessageFatal { } std::ostringstream &stream() { return log_stream_; } ~LogMessageFatal() DMLC_THROW_EXCEPTION { +#if DMLC_LOG_STACK_TRACE + const int MAX_STACK_SIZE = 10; + void *stack[MAX_STACK_SIZE]; + + int nframes = backtrace(stack, MAX_STACK_SIZE); + log_stream_ << "\n\n" << "Stack trace returned " << nframes << " entries:\n"; + char **msgs = backtrace_symbols(stack, nframes); + if (msgs != nullptr) { + for (int i = 0; i < nframes; ++i) { + log_stream_ << "[bt] (" << i << ") " << msgs[i] << "\n"; + } + } +#endif + // throwing out of destructor is evil // hopefully we can do it here // also log the message before throw diff --git a/include/rabit/rabit.h b/include/rabit/rabit.h index cf79bd638..1eda2ea76 100644 --- a/include/rabit/rabit.h +++ b/include/rabit/rabit.h @@ -15,9 +15,13 @@ // whether or not use c++11 support #ifndef DMLC_USE_CXX11 -#define DMLC_USE_CXX11 (defined(__GXX_EXPERIMENTAL_CXX0X__) ||\ - __cplusplus >= 201103L || defined(_MSC_VER)) +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_MSC_VER) +#define DMLC_USE_CXX11 1 +#else +#define DMLC_USE_CXX11 (__cplusplus >= 201103L) #endif +#endif + // optionally support of lambda functions in C++11, if available #if DMLC_USE_CXX11 #include