Merge branch 'develop' into feature/cubiquity-version

This commit is contained in:
David Williams 2014-01-31 21:20:04 +01:00
commit 376ce595d6
7 changed files with 111 additions and 365 deletions

View File

@ -5,45 +5,42 @@ PolyVox includes a number of error handling features designed to help you identi
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.
PolyVox has a simple logging mechanism which allows it to write messages with an associated severity (from Debug up to Fatal). This logging mechanism is not really intended for use by client code (i.e. calling the logging macros from your own application) but you can of course do so at your own risk. However, 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 used as follows within PolyVox (note that newlines are appended automatically):
Fatal messages are only issued in non-recoverable scenarios when the application is about to crash, and may provide the last piece of information you have about what went wrong. Error messages are issued when something has happened which prevents successful 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).
To redirect log messages you can subclass Logger, create an instance, and set it as active as follows::
.. sourcecode :: c++
logTrace() << "Trace Message";
logDebug() << "Debug Message";
logInfo() << "Info Message";
logWarning() << "Warning Message";
logError() << "Error Message";
logFatal() << "Fatal Message";
class CustomLogger : public Logger
{
public:
CustomLogger() : Logger() {}
virtual ~CustomLogger() {}
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.
To redirect log messages you can provide an implementation of std::ostream and apply it with one of the functions below:
.. sourcecode :: c++
setTraceStream(&myOutputStream);
setDebugStream(&myOutputStream);
setInfoStream(&myOutputStream);
setWarningStream(&myOutputStream);
setErrorStream(&myOutputStream);
setFatalStream(&myOutputStream);
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++
setTraceStream(getNullStream());
void logTraceMessage(const std::string& message) { /* Do something with the message */ }
void logDebugMessage(const std::string& message) { /* Do something with the message */ }
void logInfoMessage(const std::string& message) { /* Do something with the message */ }
void logWarningMessage(const std::string& message) { /* Do something with the message */ }
void logErrorMessage(const std::string& message) { /* Do something with the message */ }
void logFatalMessage(const std::string& message) { /* Do something with the message */ }
};
Or you could direct it to std::cout with:
CustomLogger* myCustomLogger = new CustomLogger();
setLogger(myCustomLogger);
When shutting down you should then do something like the following:
.. sourcecode :: c++
setTraceStream(&(std::cout));
setLogger(myCustomLogger);
delete myCustomLogger;
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.
Note that the default implementation (DefaultLogger) sends the fatal, error and warning streams to std::cerr, the info stream to std:cout, and that the debug and trace streams are suppressed.
PolyVox logging can be disabled completely in Config.h by undefining POLYVOX_LOG_TRACE_ENABLED through to POLYVOX_LOG_FATAL_ENABLED. Each of these can be disabled individually and the corresponding code will then be completely stripped from PolyVox. This is a compile-time setting - if you wish to change the log level at run-time then in your own implementation you could implement a filtering mechanism which only does something with the messages if some 'log severity' setting is greater than a certain threshold which can be changed at runtime.
Exceptions
==========

View File

@ -68,9 +68,6 @@ void createSphereInVolume(SimpleVolume<uint8_t>& volData, float fRadius)
int main(int argc, char *argv[])
{
// Show logs
setTraceStream(&(std::cout));
//Create and show the Qt OpenGL window
QApplication app(argc, argv);
OpenGLWidget openGLWidget(0);

View File

@ -24,7 +24,7 @@ freely, subject to the following restrictions:
#ifndef __PolyVox_Config_H__
#define __PolyVox_Config_H__
#define POLYVOX_LOG_TRACE_ENABLED
//#define POLYVOX_LOG_TRACE_ENABLED
#define POLYVOX_LOG_DEBUG_ENABLED
#define POLYVOX_LOG_INFO_ENABLED
#define POLYVOX_LOG_WARNING_ENABLED

View File

@ -83,13 +83,15 @@ freely, subject to the following restrictions:
{ \
if (!(condition)) \
{ \
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"; \
std::stringstream ss; \
ss << "\n"; \
ss << " PolyVox Assertion Failed!"; \
ss << " ========================="; \
ss << " Condition: " << #condition; \
ss << " Message: " << (message); \
ss << " Location: " << "Line " << __LINE__ << " of " << __FILE__; \
ss << "\n"; \
PolyVox::Impl::getLoggerInstance()->logFatalMessage(ss.str()); \
POLYVOX_HALT(); \
} \
} while(0) \
@ -154,8 +156,10 @@ freely, subject to the following restrictions:
{ \
if ((condition)) \
{ \
PolyVox::logError() << (message); \
throw type((message)); \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
throw type(ss.str()); \
} \
} while(0) \
POLYVOX_MSC_WARNING_POP
@ -168,8 +172,10 @@ freely, subject to the following restrictions:
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
PolyVox::logError() << (message); \
throw type((message)); \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
throw type(ss.str()); \
} while(0) \
POLYVOX_MSC_WARNING_POP
@ -192,8 +198,10 @@ freely, subject to the following restrictions:
{ \
if ((condition)) \
{ \
PolyVox::logError() << (message); \
type except = (type)((message)); \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
type except = (type)(ss.str()); \
getThrowHandler()((except), __FILE__, __LINE__); \
} \
} while(0) \
@ -207,8 +215,10 @@ freely, subject to the following restrictions:
POLYVOX_DISABLE_MSC_WARNING(4127) \
do \
{ \
PolyVox::logError() << (message); \
type except = (type)((message)); \
std::stringstream ss; \
ss << message; \
PolyVox::Impl::getLoggerInstance()->logErrorMessage(ss.str()); \
type except = (type)(ss.str()); \
getThrowHandler()((except), __FILE__, __LINE__); \
} while(0) \
POLYVOX_MSC_WARNING_POP

View File

@ -74,112 +74,6 @@ namespace PolyVox
}
void setLogger(Logger* pLogger);
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);
// 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);
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);
// Automatically appending 'std::endl' as described here: http://stackoverflow.com/a/2179782
struct logTrace
{
logTrace(){}
~logTrace(){*(Impl::getTraceStreamInstance()) << std::endl;}
template<class T>
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<class T>
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<class T>
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<class T>
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<class T>
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<class T>
logFatal &operator<<(const T &x)
{
*(Impl::getFatalStreamInstance()) << x;
return *this;
}
};
}
#ifdef POLYVOX_LOG_TRACE_ENABLED
@ -217,23 +111,12 @@ namespace PolyVox
#else
#define POLYVOX_LOG_TRACE(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_TRACE_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_TRACE(message)
#define POLYVOX_LOG_TRACE_IF(condition, message)
#endif
@ -272,23 +155,12 @@ namespace PolyVox
#else
#define POLYVOX_LOG_DEBUG(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_DEBUG_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_DEBUG(message)
#define POLYVOX_LOG_DEBUG_IF(condition, message)
#endif
@ -327,23 +199,12 @@ namespace PolyVox
#else
#define POLYVOX_LOG_INFO(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_INFO_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_INFO(message)
#define POLYVOX_LOG_INFO_IF(condition, message)
#endif
@ -382,23 +243,12 @@ namespace PolyVox
#else
#define POLYVOX_LOG_WARNING(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_WARNING_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_WARNING(message)
#define POLYVOX_LOG_WARNING_IF(condition, message)
#endif
@ -437,23 +287,12 @@ namespace PolyVox
#else
#define POLYVOX_LOG_ERROR(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_ERROR_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_ERROR(message)
#define POLYVOX_LOG_ERROR_IF(condition, message)
#endif
@ -492,23 +331,12 @@ namespace PolyVox
#else
#define POLYVOX_LOG_FATAL(message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
#define POLYVOX_LOG_FATAL_IF(condition, message) \
/* We use the do...while(0) construct in our macros (for reasons see here: http://stackoverflow.com/a/154138) \
but Visual Studio gives unhelpful 'conditional expression is constant' warnings. The recommended solution \
(http://stackoverflow.com/a/1946485) is to disable these warnings. */ \
POLYVOX_MSC_WARNING_PUSH \
POLYVOX_DISABLE_MSC_WARNING(4127) \
do { POLYVOX_UNUSED(condition); POLYVOX_UNUSED(message); } while(0) \
POLYVOX_MSC_WARNING_POP
// We don't bother with the do...while(0) construct here as we're not executing multiple statements
// We also don't bother with forcing variables to be 'used'. If this causes a problem then calling
// code can just force them to be used itself in addition to calling the logging macro. Basically
// we just want to reduce the chance of extra code being generated.
#define POLYVOX_LOG_FATAL(message)
#define POLYVOX_LOG_FATAL_IF(condition, message)
#endif

View File

@ -29,27 +29,29 @@ namespace PolyVox
#ifndef POLYVOX_THROW_ENABLED
void defaultThrowHandler(std::exception& e, const char* file, int line)
{
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"; \
std::stringstream ss; \
ss << "\n"; \
ss << " PolyVox exception thrown!"; \
ss << " ========================="; \
ss << " PolyVox has tried to throw an exception but it was built without support"; \
ss << " for exceptions. In this scenario PolyVox will call a 'throw handler'"; \
ss << " and this message is being printed by the default throw handler."; \
ss << "\n"; \
ss << " If you don't want to enable exceptions then you should try to determine why"; \
ss << " this exception was thrown and make sure it doesn't happen again. If it was"; \
ss << " due to something like an invalid argument to a function then you should be"; \
ss << " able to fix it quite easily by validating parameters as appropriate. More"; \
ss << " complex exception scenarios (out of memory, etc) might be harder to fix and"; \
ss << " you should replace this default handler with something which is more"; \
ss << " meaningful to your users."; \
ss << "\n"; \
ss << " Exception details"; \
ss << " -----------------"; \
ss << " Line: " << line; \
ss << " File: " << file; \
ss << " Message: " << e.what(); \
ss << "\n"; \
PolyVox::Impl::getLoggerInstance()->logFatalMessage(ss.str()); \
POLYVOX_HALT(); \
}

View File

@ -40,92 +40,4 @@ namespace PolyVox
{
Impl::getLoggerInstance() = pLogger;
}
/**
* \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(0);
return &s_NullStream;
}
// These create the global stream instances, created on demand.
namespace Impl
{
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)
{
Impl::getTraceStreamInstance() = pStream;
}
void setDebugStream(std::ostream* pStream)
{
Impl::getDebugStreamInstance() = pStream;
}
void setInfoStream(std::ostream* pStream)
{
Impl::getInfoStreamInstance() = pStream;
}
void setWarningStream(std::ostream* pStream)
{
Impl::getWarningStreamInstance() = pStream;
}
void setErrorStream(std::ostream* pStream)
{
Impl::getErrorStreamInstance() = pStream;
}
// Fatal stream for logging
std::ostream*& getFatalStreamInstance()
{
static std::ostream* s_pFatalStream = &(std::cerr);
return s_pFatalStream;
}
void setFatalStream(std::ostream* pStream)
{
getFatalStreamInstance() = pStream;
}
}