Lunchbox  1.4.0
log.h
Go to the documentation of this file.
00001 
00002 /* Copyright (c) 2005-2012, Stefan Eilemann <eile@equalizergraphics.com>
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  *
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00026 #ifndef LUNCHBOX_LOG_H
00027 #define LUNCHBOX_LOG_H
00028 
00029 #include <lunchbox/api.h>
00030 #include <lunchbox/types.h>
00031 
00032 #include <assert.h>
00033 #include <iomanip>
00034 #include <iostream>
00035 #include <sstream>
00036 
00037 namespace lunchbox
00038 {
00040     enum LogLevel
00041     {
00042         LOG_ERROR = 1, 
00043         LOG_WARN,      
00044         LOG_INFO,      
00045         LOG_VERB,      
00046         LOG_ALL
00047     };
00048 
00055     enum LogTopic
00056     {
00057         LOG_CUSTOM = 0x10,       
00058         LOG_ANY    = 0xffffu     
00059     };
00060 
00062     class LogBuffer : public std::streambuf
00063     {
00064     public:
00065         LogBuffer( std::ostream& stream )
00066                 : _line(0), _indent(0), _blocked(0), _noHeader(0),
00067                   _newLine(true), _stream(stream)
00068             { _thread[0] = 0; }
00069         virtual ~LogBuffer() {}
00070 
00071         void indent() { ++_indent; }
00072         void exdent() { --_indent; }
00073 
00074         void disableFlush() { ++_blocked; assert( _blocked < 100 ); }
00075         void enableFlush()
00076             {
00077                 assert( _blocked );// Too many enableFlush on log stream
00078                 --_blocked;
00079             }
00080 
00081         void disableHeader() { ++_noHeader; } // use counted variable to allow
00082         void enableHeader()  { --_noHeader; } //   nested enable/disable calls
00083 
00084         LUNCHBOX_API void setThreadName( const std::string& name );
00085         const char* getThreadName() const { return _thread; }
00086 
00087         void setLogInfo( const char* file, const int line )
00088             { _file = file; _line = line; }
00089 
00090     protected:
00091         virtual int_type overflow( LogBuffer::int_type c );
00092 
00093         virtual int sync();
00094 
00095     private:
00096         LogBuffer( const LogBuffer& );
00097         LogBuffer& operator = ( const LogBuffer& );
00098 
00100         char _thread[12];
00101 
00103         std::string _file;
00104 
00106         int _line;
00107 
00109         int _indent;
00110 
00112         int _blocked;
00113 
00115         int _noHeader;
00116 
00118         bool _newLine;
00119 
00121         std::ostringstream _stringStream;
00122 
00124         std::ostream& _stream;
00125 
00127         static Lock _lock;
00128     };
00129 
00131     class Log : public std::ostream
00132     {
00133     public:
00134 
00135         Log() : std::ostream( &_logBuffer ), _logBuffer( getOutput( )){}
00136         virtual ~Log() { _logBuffer.pubsync(); }
00137 
00138         void indent() { _logBuffer.indent(); }
00139         void exdent() { _logBuffer.exdent(); }
00140         void disableFlush() { _logBuffer.disableFlush(); }
00141         void enableFlush()  { _logBuffer.enableFlush();  }
00142         void forceFlush()  { _logBuffer.pubsync();  }
00143         void disableHeader() { _logBuffer.disableHeader(); }
00144         void enableHeader()  { _logBuffer.enableHeader();  }
00145 
00147         static LUNCHBOX_API int level;
00148 
00150         static LUNCHBOX_API unsigned topics;
00151 
00153         static LUNCHBOX_API Log& instance();
00154 
00156         static LUNCHBOX_API Log& instance( const char* file, const int line );
00157 
00159         static LUNCHBOX_API void exit();
00160 
00162         static std::string& getLogLevelString();
00163 
00165         static LUNCHBOX_API int getLogLevel( const char* level );
00166 
00168         static LUNCHBOX_API void setOutput( std::ostream& stream );
00169 
00171         static LUNCHBOX_API std::ostream& getOutput ();
00172 
00181         static LUNCHBOX_API void setClock( Clock* clock );
00182 
00184         void setThreadName( const std::string& name )
00185             { _logBuffer.setThreadName( name ); }
00186 
00188         const char* getThreadName() const { return _logBuffer.getThreadName(); }
00189 
00190     private:
00191         LogBuffer _logBuffer;
00192 
00193         Log( const Log& );
00194         Log& operator = ( const Log& );
00195 
00196         void setLogInfo( const char* file, const int line )
00197             { _logBuffer.setLogInfo( file, line ); }
00198     };
00199 
00205     LUNCHBOX_API std::ostream& indent( std::ostream& os );
00207     LUNCHBOX_API std::ostream& exdent( std::ostream& os );
00208 
00210     LUNCHBOX_API std::ostream& disableFlush( std::ostream& os );
00212     LUNCHBOX_API std::ostream& enableFlush( std::ostream& os );
00214     LUNCHBOX_API std::ostream& forceFlush( std::ostream& os );
00215 
00217     LUNCHBOX_API std::ostream& disableHeader( std::ostream& os );
00219     LUNCHBOX_API std::ostream& enableHeader( std::ostream& os );
00220 }
00221 
00223 #define LBERROR (lunchbox::Log::level >= lunchbox::LOG_ERROR) &&    \
00224     lunchbox::Log::instance( __FILE__, __LINE__ )
00225 
00226 #define LBWARN  (lunchbox::Log::level >= lunchbox::LOG_WARN)  &&    \
00227     lunchbox::Log::instance( __FILE__, __LINE__ )
00228 
00229 #define LBINFO  (lunchbox::Log::level >= lunchbox::LOG_INFO)  &&    \
00230     lunchbox::Log::instance( __FILE__, __LINE__ )
00231 
00232 #ifdef NDEBUG
00233 #  define LBVERB if( false )                                    \
00234         lunchbox::Log::instance( __FILE__, __LINE__ )
00235 #else
00236 
00237 #  define LBVERB (lunchbox::Log::level >= lunchbox::LOG_VERB)  &&    \
00238     lunchbox::Log::instance( __FILE__, __LINE__ )
00239 #endif
00240 
00245 #define LBLOG(topic)  (lunchbox::Log::topics & (topic))  &&  \
00246     lunchbox::Log::instance( __FILE__, __LINE__ )
00247 
00248 #endif //LUNCHBOX_LOG_H