From f3b01830139fb04fbb6bdc1086d536e7d69ba618 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Wed, 22 May 2013 14:21:50 +0200 Subject: [PATCH 1/8] Switching to a stream-based interface for logging. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 55 +++----- .../PolyVoxCore/source/Impl/ErrorHandling.cpp | 120 +++++------------- 2 files changed, 52 insertions(+), 123 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index c81c8221..c48255d4 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -62,36 +62,19 @@ freely, subject to the following restrictions: * PolyVox provides basic logging facilities which can be redirected by your application. */ +#define LOG_DECLARATION(name) \ + std::ostream& log(name)(void); \ + void set(name)Stream(std::ostream& nameStream); + namespace PolyVox { - class LogLevels - { - public: - enum LogLevel - { - Debug, - Info, - Warning, - Error, - Fatal - }; - }; - typedef LogLevels::LogLevel LogLevel; + std::ostream& logError(void); + std::ostream& logFatal(void); - typedef void (*LogHandler)(const std::string& message, LogLevel logLevel); - - LogHandler getLogHandler(); - void setLogHandler(LogHandler newHandler); - - // The actual logging function - void log(const std::string& message, LogLevel logLevel); - - // Some handy wrappers - void logDebug (const std::string& message); - void logInfo (const std::string& message); - void logWarning(const std::string& message); - void logError (const std::string& message); - void logFatal (const std::string& message); + // These take pointers rather than references to emphasise that the + // user needs to keep the target alive as long as PolyVox is writing data. + void setErrorStream(std::ostream* errorStream); + void setFatalStream(std::ostream* fatalStream); } /* @@ -114,14 +97,12 @@ namespace PolyVox { \ if (!(condition)) \ { \ - std::stringstream ss; \ - ss << std::endl << std::endl; \ - ss << " PolyVox Assertion Failed!" << std::endl; \ - ss << " =========================" << std::endl; \ - ss << " Condition: " << #condition << std::endl; \ - ss << " Message: " << (message) << std::endl; \ - ss << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ - PolyVox::logFatal(ss.str()); \ + logFatal() << std::endl << std::endl; \ + logFatal() << " PolyVox Assertion Failed!" << std::endl; \ + logFatal() << " =========================" << std::endl; \ + logFatal() << " Condition: " << #condition << std::endl; \ + logFatal() << " Message: " << (message) << std::endl; \ + logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ POLYVOX_HALT(); \ } \ } while(0) \ @@ -176,7 +157,7 @@ namespace PolyVox */ #ifdef POLYVOX_THROW_ENABLED #define POLYVOX_THROW(type, message) \ - PolyVox::logError(message); \ + logError() << (message); \ throw type((message)) #else namespace PolyVox @@ -188,7 +169,7 @@ namespace PolyVox } #define POLYVOX_THROW(type, message) \ - PolyVox::logError(message); \ + logError() << (message); \ type except = (type)((message)); \ getThrowHandler()((except), __FILE__, __LINE__) #endif diff --git a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp index 8e90bb3e..8cef5e6d 100644 --- a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp +++ b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp @@ -25,115 +25,63 @@ freely, subject to the following restrictions: namespace PolyVox { - void defaultLogHandler(const std::string& message, LogLevel logLevel) + // Error stream for logging + std::ostream*& getErrorStreamInstance() { - switch(logLevel) - { - case LogLevels::Debug: - { - // Debug messages are not output by this default log handler. - // Provide a custom handler if you want to process them. - break; - } - case LogLevels::Info: - { - std::cout << "Info: " << message.c_str() << std::endl; - break; - } - case LogLevels::Warning: - { - std::cerr << "Warning: " << message.c_str() << std::endl; - break; - } - case LogLevels::Error: - { - std::cerr << "Error: " << message.c_str() << std::endl; - break; - } - case LogLevels::Fatal: - { - std::cerr << "Fatal: " << message.c_str() << std::endl; - break; - } - } + static std::ostream* s_pErrorStream = &(std::cerr); + return s_pErrorStream; } - LogHandler& getLogHandlerInstance() + void setErrorStream(std::ostream* errorStream) { - static LogHandler s_fLogHandler = &defaultLogHandler; - return s_fLogHandler; + getErrorStreamInstance() = errorStream; } - LogHandler getLogHandler() + std::ostream& logError(void) { - return getLogHandlerInstance(); + return *(getErrorStreamInstance()); } - void setLogHandler(LogHandler fNewHandler) + // Fatal stream for logging + std::ostream*& getFatalStreamInstance() { - getLogHandlerInstance() = fNewHandler; + static std::ostream* s_pFatalStream = &(std::cerr); + return s_pFatalStream; } - void log(const std::string& message, LogLevel logLevel) + void setFatalStream(std::ostream* fatalStream) { - LogHandler logHandler = getLogHandler(); - if(logHandler) - { - logHandler(message, logLevel); - } + getFatalStreamInstance() = fatalStream; } - // Some handy wrappers - void logDebug(const std::string& message) - { - log(message, LogLevels::Debug ); - } - - void logInfo(const std::string& message) + std::ostream& logFatal(void) { - log(message, LogLevels::Info); - } - - void logWarning(const std::string& message) - { - log(message, LogLevels::Warning); - } - - void logError(const std::string& message) - { - log(message, LogLevels::Error); - } - - void logFatal(const std::string& message) - { - log(message, LogLevels::Fatal); + return *(getFatalStreamInstance()); } #ifndef POLYVOX_THROW_ENABLED void defaultThrowHandler(std::exception& e, const char* file, int line) { - std::stringstream ss; \ - ss << std::endl << std::endl; \ - ss << " PolyVox exception thrown!" << std::endl; \ - ss << " =========================" << std::endl; \ - ss << " PolyVox has tried to throw an exception but it was built without support" << std::endl; \ - ss << " for exceptions. In this scenario PolyVox will call a 'throw handler'" << std::endl; \ - ss << " and this message is being printed by the default throw handler." << std::endl << std::endl; \ + logFatal() << std::endl << std::endl; \ + logFatal() << " PolyVox exception thrown!" << std::endl; \ + logFatal() << " =========================" << std::endl; \ + logFatal() << " PolyVox has tried to throw an exception but it was built without support" << std::endl; \ + logFatal() << " for exceptions. In this scenario PolyVox will call a 'throw handler'" << std::endl; \ + logFatal() << " and this message is being printed by the default throw handler." << std::endl << std::endl; \ - ss << " If you don't want to enable exceptions then you should try to determine why" << std::endl; \ - ss << " this exception was thrown and make sure it doesn't happen again. If it was" << std::endl; \ - ss << " due to something like an invalid argument to a function then you should be" << std::endl; \ - ss << " able to fix it quite easily by validating parameters as appropriate. More" << std::endl; \ - ss << " complex exception scenarios (out of memory, etc) might be harder to fix and" << std::endl; \ - ss << " you should replace this default handler with something which is more" << std::endl; \ - ss << " meaningful to your users." << std::endl << std::endl; \ + logFatal() << " If you don't want to enable exceptions then you should try to determine why" << std::endl; \ + logFatal() << " this exception was thrown and make sure it doesn't happen again. If it was" << std::endl; \ + logFatal() << " due to something like an invalid argument to a function then you should be" << std::endl; \ + logFatal() << " able to fix it quite easily by validating parameters as appropriate. More" << std::endl; \ + logFatal() << " complex exception scenarios (out of memory, etc) might be harder to fix and" << std::endl; \ + logFatal() << " you should replace this default handler with something which is more" << std::endl; \ + logFatal() << " meaningful to your users." << std::endl << std::endl; \ - ss << " Exception details" << std::endl; \ - ss << " -----------------" << std::endl; \ - ss << " Line: " << line << std::endl; \ - ss << " File: " << file << std::endl; \ - ss << " Message: " << e.what() << std::endl << std::endl; \ - PolyVox::logFatal(ss.str()); \ + logFatal() << " Exception details" << std::endl; \ + logFatal() << " -----------------" << std::endl; \ + logFatal() << " Line: " << line << std::endl; \ + logFatal() << " File: " << file << std::endl; \ + logFatal() << " Message: " << e.what() << std::endl << std::endl; \ POLYVOX_HALT(); \ } From 6c77e778ddf1e4b2fca595c2634e0e54ee715956 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Wed, 22 May 2013 15:18:08 +0200 Subject: [PATCH 2/8] Added namespace qualifiers. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index c48255d4..17a31107 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -97,12 +97,12 @@ namespace PolyVox { \ if (!(condition)) \ { \ - logFatal() << std::endl << std::endl; \ - logFatal() << " PolyVox Assertion Failed!" << std::endl; \ - logFatal() << " =========================" << std::endl; \ - logFatal() << " Condition: " << #condition << std::endl; \ - logFatal() << " Message: " << (message) << std::endl; \ - logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ + PolyVox::logFatal() << std::endl << std::endl; \ + PolyVox::logFatal() << " PolyVox Assertion Failed!" << std::endl; \ + PolyVox::logFatal() << " =========================" << std::endl; \ + PolyVox::logFatal() << " Condition: " << #condition << std::endl; \ + PolyVox::logFatal() << " Message: " << (message) << std::endl; \ + PolyVox::logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ POLYVOX_HALT(); \ } \ } while(0) \ @@ -157,7 +157,7 @@ namespace PolyVox */ #ifdef POLYVOX_THROW_ENABLED #define POLYVOX_THROW(type, message) \ - logError() << (message); \ + PolyVox::logError() << (message); \ throw type((message)) #else namespace PolyVox @@ -169,7 +169,7 @@ namespace PolyVox } #define POLYVOX_THROW(type, message) \ - logError() << (message); \ + PolyVox::logError() << (message); \ type except = (type)((message)); \ getThrowHandler()((except), __FILE__, __LINE__) #endif From b12e6d045c140e3064aa90d279001be4479a26a2 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Fri, 24 May 2013 13:26:26 +0200 Subject: [PATCH 3/8] Added additional logging streams. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 12 ++- .../PolyVoxCore/source/Impl/ErrorHandling.cpp | 76 ++++++++++++++++++- 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index 17a31107..d40a561a 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -68,13 +68,21 @@ freely, subject to the following restrictions: namespace PolyVox { + std::ostream& logTrace(void); + std::ostream& logDebug(void); + std::ostream& logInfo(void); + std::ostream& logWarning(void); std::ostream& logError(void); std::ostream& logFatal(void); // These take pointers rather than references to emphasise that the // user needs to keep the target alive as long as PolyVox is writing data. - void setErrorStream(std::ostream* errorStream); - void setFatalStream(std::ostream* fatalStream); + void setTraceStream(std::ostream* pStream); + void setDebugStream(std::ostream* pStream); + void setInfoStream(std::ostream* pStream); + void setWarningStream(std::ostream* pStream); + void setErrorStream(std::ostream* pStream); + void setFatalStream(std::ostream* pStream); } /* diff --git a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp index 8cef5e6d..cce96bef 100644 --- a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp +++ b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp @@ -25,6 +25,74 @@ freely, subject to the following restrictions: namespace PolyVox { + // Trace stream for logging + std::ostream*& getTraceStreamInstance() + { + static std::ostream* s_pTraceStream = &(std::cerr); + return s_pTraceStream; + } + + void setTraceStream(std::ostream* pStream) + { + getTraceStreamInstance() = pStream; + } + + std::ostream& logTrace(void) + { + return *(getTraceStreamInstance()); + } + + // Debug stream for logging + std::ostream*& getDebugStreamInstance() + { + static std::ostream* s_pDebugStream = &(std::cerr); + return s_pDebugStream; + } + + void setDebugStream(std::ostream* pStream) + { + getDebugStreamInstance() = pStream; + } + + std::ostream& logDebug(void) + { + return *(getDebugStreamInstance()); + } + + // Info stream for logging + std::ostream*& getInfoStreamInstance() + { + static std::ostream* s_pInfoStream = &(std::cerr); + return s_pInfoStream; + } + + void setInfoStream(std::ostream* pStream) + { + getInfoStreamInstance() = pStream; + } + + std::ostream& logInfo(void) + { + return *(getInfoStreamInstance()); + } + + // Warning stream for logging + std::ostream*& getWarningStreamInstance() + { + static std::ostream* s_pWarningStream = &(std::cerr); + return s_pWarningStream; + } + + void setWarningStream(std::ostream* pStream) + { + getWarningStreamInstance() = pStream; + } + + std::ostream& logWarning(void) + { + return *(getWarningStreamInstance()); + } + // Error stream for logging std::ostream*& getErrorStreamInstance() { @@ -32,9 +100,9 @@ namespace PolyVox return s_pErrorStream; } - void setErrorStream(std::ostream* errorStream) + void setErrorStream(std::ostream* pStream) { - getErrorStreamInstance() = errorStream; + getErrorStreamInstance() = pStream; } std::ostream& logError(void) @@ -49,9 +117,9 @@ namespace PolyVox return s_pFatalStream; } - void setFatalStream(std::ostream* fatalStream) + void setFatalStream(std::ostream* pStream) { - getFatalStreamInstance() = fatalStream; + getFatalStreamInstance() = pStream; } std::ostream& logFatal(void) From c1461e75826c9d8488b644bd8de1503d29e7b938 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Fri, 24 May 2013 13:51:52 +0200 Subject: [PATCH 4/8] Added a null stream to suppress logging. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 3 +++ .../PolyVoxCore/source/Impl/ErrorHandling.cpp | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index d40a561a..b5100b25 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -68,6 +68,9 @@ freely, subject to the following restrictions: namespace PolyVox { + /// Get a stream which will consume all input without outputting anything. + std::ostream* getNullStream(void); + std::ostream& logTrace(void); std::ostream& logDebug(void); std::ostream& logInfo(void); diff --git a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp index cce96bef..a3c2dedc 100644 --- a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp +++ b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp @@ -25,10 +25,21 @@ freely, subject to the following restrictions: namespace PolyVox { + /** + * \return A pointer to the null stream. + */ + std::ostream* getNullStream(void) + { + // Passing zero to the stream constructor guarentees it will discard all input. See + // here http://stackoverflow.com/a/8244052 and here http://stackoverflow.com/a/6240980 + static std::ostream s_NullStream = std::ostream(0); + return &s_NullStream; + } + // Trace stream for logging std::ostream*& getTraceStreamInstance() { - static std::ostream* s_pTraceStream = &(std::cerr); + static std::ostream* s_pTraceStream = getNullStream(); return s_pTraceStream; } @@ -45,7 +56,7 @@ namespace PolyVox // Debug stream for logging std::ostream*& getDebugStreamInstance() { - static std::ostream* s_pDebugStream = &(std::cerr); + static std::ostream* s_pDebugStream = getNullStream(); return s_pDebugStream; } @@ -62,7 +73,7 @@ namespace PolyVox // Info stream for logging std::ostream*& getInfoStreamInstance() { - static std::ostream* s_pInfoStream = &(std::cerr); + static std::ostream* s_pInfoStream = &(std::cout); return s_pInfoStream; } From d12a81d3452641c1c29b5ed6d23b1cfacbb04f54 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Fri, 24 May 2013 16:00:19 +0200 Subject: [PATCH 5/8] Log messages now automatically have std::endl applied, and work/behave similar to Qt logging functions. --- .../include/PolyVoxCore/Impl/ErrorHandling.h | 114 +++++++++++-- .../PolyVoxCore/source/Impl/ErrorHandling.cpp | 151 ++++++++---------- 2 files changed, 164 insertions(+), 101 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h index b5100b25..847ae008 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/ErrorHandling.h @@ -68,16 +68,19 @@ freely, subject to the following restrictions: namespace PolyVox { + namespace Impl + { + std::ostream*& getTraceStreamInstance(); + std::ostream*& getDebugStreamInstance(); + std::ostream*& getInfoStreamInstance(); + std::ostream*& getWarningStreamInstance(); + std::ostream*& getErrorStreamInstance(); + std::ostream*& getFatalStreamInstance(); + } + /// Get a stream which will consume all input without outputting anything. std::ostream* getNullStream(void); - std::ostream& logTrace(void); - std::ostream& logDebug(void); - std::ostream& logInfo(void); - std::ostream& logWarning(void); - std::ostream& logError(void); - std::ostream& logFatal(void); - // These take pointers rather than references to emphasise that the // user needs to keep the target alive as long as PolyVox is writing data. void setTraceStream(std::ostream* pStream); @@ -86,6 +89,90 @@ namespace PolyVox void setWarningStream(std::ostream* pStream); void setErrorStream(std::ostream* pStream); void setFatalStream(std::ostream* pStream); + + // Automatically appending 'std::endl' as described here: http://stackoverflow.com/a/2179782 + struct logTrace + { + logTrace(){} + ~logTrace(){*(Impl::getTraceStreamInstance()) << std::endl;} + + template + logTrace &operator<<(const T &x) + { + *(Impl::getTraceStreamInstance()) << x; + return *this; + } + }; + + // Automatically appending 'std::endl' as described here: http://stackoverflow.com/a/2179782 + struct logDebug + { + logDebug(){} + ~logDebug(){*(Impl::getDebugStreamInstance()) << std::endl;} + + template + logDebug &operator<<(const T &x) + { + *(Impl::getDebugStreamInstance()) << x; + return *this; + } + }; + + // Automatically appending 'std::endl' as described here: http://stackoverflow.com/a/2179782 + struct logInfo + { + logInfo(){} + ~logInfo(){*(Impl::getInfoStreamInstance()) << std::endl;} + + template + logInfo &operator<<(const T &x) + { + *(Impl::getInfoStreamInstance()) << x; + return *this; + } + }; + + // Automatically appending 'std::endl' as described here: http://stackoverflow.com/a/2179782 + struct logWarning + { + logWarning(){} + ~logWarning(){*(Impl::getWarningStreamInstance()) << std::endl;} + + template + logWarning &operator<<(const T &x) + { + *(Impl::getWarningStreamInstance()) << x; + return *this; + } + }; + + // Automatically appending 'std::endl' as described here: http://stackoverflow.com/a/2179782 + struct logError + { + logError(){} + ~logError(){*(Impl::getErrorStreamInstance()) << std::endl;} + + template + logError &operator<<(const T &x) + { + *(Impl::getErrorStreamInstance()) << x; + return *this; + } + }; + + // Automatically appending 'std::endl' as described here: http://stackoverflow.com/a/2179782 + struct logFatal + { + logFatal(){} + ~logFatal(){*(Impl::getFatalStreamInstance()) << std::endl;} + + template + logFatal &operator<<(const T &x) + { + *(Impl::getFatalStreamInstance()) << x; + return *this; + } + }; } /* @@ -108,12 +195,13 @@ namespace PolyVox { \ if (!(condition)) \ { \ - PolyVox::logFatal() << std::endl << std::endl; \ - PolyVox::logFatal() << " PolyVox Assertion Failed!" << std::endl; \ - PolyVox::logFatal() << " =========================" << std::endl; \ - PolyVox::logFatal() << " Condition: " << #condition << std::endl; \ - PolyVox::logFatal() << " Message: " << (message) << std::endl; \ - PolyVox::logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__ << std::endl << std::endl; \ + PolyVox::logFatal() << "\n"; \ + PolyVox::logFatal() << " PolyVox Assertion Failed!"; \ + PolyVox::logFatal() << " ========================="; \ + PolyVox::logFatal() << " Condition: " << #condition; \ + PolyVox::logFatal() << " Message: " << (message); \ + PolyVox::logFatal() << " Location: " << "Line " << __LINE__ << " of " << __FILE__; \ + PolyVox::logFatal() << "\n"; \ POLYVOX_HALT(); \ } \ } while(0) \ diff --git a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp index a3c2dedc..baeae6be 100644 --- a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp +++ b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp @@ -36,89 +36,69 @@ namespace PolyVox return &s_NullStream; } - // Trace stream for logging - std::ostream*& getTraceStreamInstance() + // These create the global stream instances, created on demand. + namespace Impl { - static std::ostream* s_pTraceStream = getNullStream(); - return s_pTraceStream; + std::ostream*& getTraceStreamInstance() + { + static std::ostream* s_pTraceStream = getNullStream(); + return s_pTraceStream; + } + + std::ostream*& getDebugStreamInstance() + { + static std::ostream* s_pDebugStream = getNullStream(); + return s_pDebugStream; + } + + std::ostream*& getInfoStreamInstance() + { + static std::ostream* s_pInfoStream = &(std::cout); + return s_pInfoStream; + } + + std::ostream*& getWarningStreamInstance() + { + static std::ostream* s_pWarningStream = &(std::cerr); + return s_pWarningStream; + } + + std::ostream*& getErrorStreamInstance() + { + static std::ostream* s_pErrorStream = &(std::cerr); + return s_pErrorStream; + } + + std::ostream*& getFatalStreamInstance() + { + static std::ostream* s_pFatalStream = &(std::cerr); + return s_pFatalStream; + } } void setTraceStream(std::ostream* pStream) { - getTraceStreamInstance() = pStream; - } - - std::ostream& logTrace(void) - { - return *(getTraceStreamInstance()); - } - - // Debug stream for logging - std::ostream*& getDebugStreamInstance() - { - static std::ostream* s_pDebugStream = getNullStream(); - return s_pDebugStream; + Impl::getTraceStreamInstance() = pStream; } void setDebugStream(std::ostream* pStream) { - getDebugStreamInstance() = pStream; - } - - std::ostream& logDebug(void) - { - return *(getDebugStreamInstance()); - } - - // Info stream for logging - std::ostream*& getInfoStreamInstance() - { - static std::ostream* s_pInfoStream = &(std::cout); - return s_pInfoStream; + Impl::getDebugStreamInstance() = pStream; } void setInfoStream(std::ostream* pStream) { - getInfoStreamInstance() = pStream; - } - - std::ostream& logInfo(void) - { - return *(getInfoStreamInstance()); - } - - // Warning stream for logging - std::ostream*& getWarningStreamInstance() - { - static std::ostream* s_pWarningStream = &(std::cerr); - return s_pWarningStream; + Impl::getInfoStreamInstance() = pStream; } void setWarningStream(std::ostream* pStream) { - getWarningStreamInstance() = pStream; - } - - std::ostream& logWarning(void) - { - return *(getWarningStreamInstance()); - } - - // Error stream for logging - std::ostream*& getErrorStreamInstance() - { - static std::ostream* s_pErrorStream = &(std::cerr); - return s_pErrorStream; + Impl::getWarningStreamInstance() = pStream; } void setErrorStream(std::ostream* pStream) { - getErrorStreamInstance() = pStream; - } - - std::ostream& logError(void) - { - return *(getErrorStreamInstance()); + Impl::getErrorStreamInstance() = pStream; } // Fatal stream for logging @@ -133,35 +113,30 @@ namespace PolyVox getFatalStreamInstance() = pStream; } - std::ostream& logFatal(void) - { - return *(getFatalStreamInstance()); - } - #ifndef POLYVOX_THROW_ENABLED void defaultThrowHandler(std::exception& e, const char* file, int line) { - logFatal() << std::endl << std::endl; \ - logFatal() << " PolyVox exception thrown!" << std::endl; \ - logFatal() << " =========================" << std::endl; \ - logFatal() << " PolyVox has tried to throw an exception but it was built without support" << std::endl; \ - logFatal() << " for exceptions. In this scenario PolyVox will call a 'throw handler'" << std::endl; \ - logFatal() << " and this message is being printed by the default throw handler." << std::endl << std::endl; \ - - logFatal() << " If you don't want to enable exceptions then you should try to determine why" << std::endl; \ - logFatal() << " this exception was thrown and make sure it doesn't happen again. If it was" << std::endl; \ - logFatal() << " due to something like an invalid argument to a function then you should be" << std::endl; \ - logFatal() << " able to fix it quite easily by validating parameters as appropriate. More" << std::endl; \ - logFatal() << " complex exception scenarios (out of memory, etc) might be harder to fix and" << std::endl; \ - logFatal() << " you should replace this default handler with something which is more" << std::endl; \ - logFatal() << " meaningful to your users." << std::endl << std::endl; \ - - logFatal() << " Exception details" << std::endl; \ - logFatal() << " -----------------" << std::endl; \ - logFatal() << " Line: " << line << std::endl; \ - logFatal() << " File: " << file << std::endl; \ - logFatal() << " Message: " << e.what() << std::endl << std::endl; \ - + logFatal() << "\n"; \ + logFatal() << " PolyVox exception thrown!"; \ + logFatal() << " ========================="; \ + logFatal() << " PolyVox has tried to throw an exception but it was built without support"; \ + logFatal() << " for exceptions. In this scenario PolyVox will call a 'throw handler'"; \ + logFatal() << " and this message is being printed by the default throw handler."; \ + logFatal() << "\n"; \ + logFatal() << " If you don't want to enable exceptions then you should try to determine why"; \ + logFatal() << " this exception was thrown and make sure it doesn't happen again. If it was"; \ + logFatal() << " due to something like an invalid argument to a function then you should be"; \ + logFatal() << " able to fix it quite easily by validating parameters as appropriate. More"; \ + logFatal() << " complex exception scenarios (out of memory, etc) might be harder to fix and"; \ + logFatal() << " you should replace this default handler with something which is more"; \ + logFatal() << " meaningful to your users."; \ + logFatal() << "\n"; \ + logFatal() << " Exception details"; \ + logFatal() << " -----------------"; \ + logFatal() << " Line: " << line; \ + logFatal() << " File: " << file; \ + logFatal() << " Message: " << e.what(); \ + logFatal() << "\n"; \ POLYVOX_HALT(); \ } From 60205425db24aec0d0d2b8c5b65c064fe35925f3 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Fri, 24 May 2013 16:18:02 +0200 Subject: [PATCH 6/8] Fixed warning about unreachable code. --- library/PolyVoxCore/include/PolyVoxCore/BaseVolumeSampler.inl | 1 - library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl | 1 - library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl | 1 - library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.inl | 1 - 4 files changed, 4 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/BaseVolumeSampler.inl b/library/PolyVoxCore/include/PolyVoxCore/BaseVolumeSampler.inl index e8300ccf..1e67a020 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/BaseVolumeSampler.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/BaseVolumeSampler.inl @@ -376,7 +376,6 @@ namespace PolyVox { //Should never happen POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); - return VoxelType(); } } } diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl index 76d4049a..a00c744f 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl @@ -230,7 +230,6 @@ namespace PolyVox { //Should never happen POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); - return VoxelType(); } } } diff --git a/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl index c6face08..dc6732e0 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl @@ -188,7 +188,6 @@ namespace PolyVox { //Should never happen POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); - return VoxelType(); } } } diff --git a/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.inl index 573f3c83..decbcfce 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/SimpleVolume.inl @@ -188,7 +188,6 @@ namespace PolyVox { //Should never happen POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); - return VoxelType(); } } } From d34ff02b0b766bda5b7857e49b9f8cd7fd9a4ca2 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Fri, 24 May 2013 16:31:36 +0200 Subject: [PATCH 7/8] Updated documentation on error handling. --- documentation/ErrorHandling.rst | 36 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/documentation/ErrorHandling.rst b/documentation/ErrorHandling.rst index 17525fab..88537a22 100644 --- a/documentation/ErrorHandling.rst +++ b/documentation/ErrorHandling.rst @@ -7,31 +7,43 @@ Logging ======= PolyVox has a simple logging mechanism which allows it to write messages with an associated severity (from Debug up to Fatal). It is possible to redirect the output of these logging functions so you can integrate them with your applications logging framework or suppress them completely. -The following functions are called at various points in the PolyVox codebase: +The following functions are used as follows within PolyVox (note that newlines are appended automatically): .. sourcecode :: c++ - void logDebug (const std::string& message); - void logInfo (const std::string& message); - void logWarning(const std::string& message); - void logError (const std::string& message); - void logFatal (const std::string& message); + logTrace() << "Trace Message"; + logDebug() << "Debug Message"; + logInfo() << "Info Message"; + logWarning() << "Warning Message"; + logError() << "Error Message"; + logFatal() << "Fatal Message"; -Fatal messages are only issued in non-recoverable scenarios when the application is about to crash, and may provide the last peice of information you have about what went wrong. Error messages are issued when something has happened which prevents sucessful completion of a task, for example if you provide invalid parameters to a function (Error messages are also issued whenever an exception is thrown). Warning messages mean the system was able to continue but the results may not be what you expected. Info and Debug messages are both used for general information about what PolyVox is doing. The differentiating factor is that Debug is used if the output is very frequent so that it can be easily suppressed. +Fatal messages are only issued in non-recoverable scenarios when the application is about to crash, and may provide the last peice of information you have about what went wrong. Error messages are issued when something has happened which prevents sucessful completion of a task, for example if you provide invalid parameters to a function (error messages are also issued whenever an exception is thrown). Warning messages mean the system was able to continue but the results may not be what you expected. Info messages are used for general information about what PolyVox is doing. Debug and trace messages produce very verbose output and a lot of detail about what PolyVox is doing internally. In general, debug messages are used for tasks the user has directly initiated (e.g. they might provide time information for surface extraction) while trace messages are used for things which happen spontaneously (such as data being paged out of memory). Trace messages are most likely to clutter up your logs and so are most easily suppressed. -PolyVox defines a LogHandler function pointer which looks like this: +To redirect log messages you can provide an implementation of std::ostream and apply it with one of the functions below: .. sourcecode :: c++ - typedef void (*LogHandler)(const std::string& message, LogLevel logLevel); + setTraceStream(&myOutputStream); + setDebugStream(&myOutputStream); + setInfoStream(&myOutputStream); + setWarningStream(&myOutputStream); + setErrorStream(&myOutputStream); + setFatalStream(&myOutputStream); -There is a function called 'defaultLogHandler()' which matches this signature and writes the messages to cout/cerr (note that it suppresses Debug messages). To redirect log messages you can write your own fuction which matches this signature and the apply it with setLogHandler: +PolyVox provides a function called 'getNullStream()' which returns a stream which consumes all input without writing it anywhere. You can use this to supress particular log streams. For example, you can suppress the Trace stream with: .. sourcecode :: c++ - setLogHandler(&myLogHandler); + setTraceStream(getNullStream()); + +Or you could direct it to std::cout with: -Note that you can disable logging completely by passing a value of '0' to setLogHandler(). +.. sourcecode :: c++ + + setTraceStream(&(std::cout))); + +Note that by default the fatal, error and warning streams go to std::cerr, the info stream goes to std:cout, and the debug and trace streams are suppressed. Exceptions ========== From a56005478d7f400302e8ab43b54da74b14793959 Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Mon, 27 May 2013 12:59:19 +0200 Subject: [PATCH 8/8] Fix for Linux compile error. --- library/PolyVoxCore/source/Impl/ErrorHandling.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp index baeae6be..18653a6b 100644 --- a/library/PolyVoxCore/source/Impl/ErrorHandling.cpp +++ b/library/PolyVoxCore/source/Impl/ErrorHandling.cpp @@ -32,7 +32,7 @@ namespace PolyVox { // Passing zero to the stream constructor guarentees it will discard all input. See // here http://stackoverflow.com/a/8244052 and here http://stackoverflow.com/a/6240980 - static std::ostream s_NullStream = std::ostream(0); + static std::ostream s_NullStream(0); return &s_NullStream; }