Lunchbox  1.8.0
log.h
Go to the documentation of this file.
1 
2 /* Copyright (c) 2005-2013, Stefan Eilemann <eile@equalizergraphics.com>
3  * 2011, Daniel Nachbaur <danielnachbaur@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License version 2.1 as published
7  * by the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
27 #ifndef LUNCHBOX_LOG_H
28 #define LUNCHBOX_LOG_H
29 
30 #include <lunchbox/api.h>
31 #include <lunchbox/types.h>
32 
33 #include <assert.h>
34 #include <iomanip>
35 #include <iostream>
36 #include <sstream>
37 
38 namespace lunchbox
39 {
41  enum LogLevel
42  {
43  LOG_ERROR = 1,
47  LOG_ALL
48  };
49 
56  enum LogTopic
57  {
58  LOG_EXCEPTION = 0x01,
59  LOG_PLUGIN = 0x02,
60  LOG_CUSTOM = 0x10,
61  LOG_ANY = 0xffffu
62  };
63 
65  class LogBuffer : public std::streambuf
66  {
67  public:
68  LogBuffer( std::ostream& stream )
69  : _line(0), _indent(0), _blocked(0), _noHeader(0),
70  _newLine(true), _stream(stream)
71  { _thread[0] = 0; }
72  virtual ~LogBuffer() {}
73 
74  void indent() { ++_indent; }
75  void exdent() { --_indent; }
76 
77  void disableFlush() { ++_blocked; assert( _blocked < 100 ); }
78  void enableFlush()
79  {
80  assert( _blocked );// Too many enableFlush on log stream
81  --_blocked;
82  }
83 
84  void disableHeader() { ++_noHeader; } // use counted variable to allow
85  void enableHeader() { --_noHeader; } // nested enable/disable calls
86 
87  LUNCHBOX_API void setThreadName( const std::string& name );
88  const char* getThreadName() const { return _thread; }
89 
90  LUNCHBOX_API void setLogInfo( const char* file, const int line );
91 
92  protected:
93  virtual int_type overflow( LogBuffer::int_type c );
94 
95  virtual int sync();
96 
97  private:
98  LogBuffer( const LogBuffer& );
99  LogBuffer& operator = ( const LogBuffer& );
100 
102  char _thread[12];
103 
105  std::string _file;
106 
108  int _line;
109 
111  int _indent;
112 
114  int _blocked;
115 
117  int _noHeader;
118 
120  bool _newLine;
121 
123  std::ostringstream _stringStream;
124 
126  std::ostream& _stream;
127 
129  static Lock _lock;
130  };
131 
133  class Log : public std::ostream
134  {
135  public:
136 
137  Log() : std::ostream( &_logBuffer ), _logBuffer( getOutput( )){}
138  virtual ~Log() { _logBuffer.pubsync(); }
139 
140  void indent() { _logBuffer.indent(); }
141  void exdent() { _logBuffer.exdent(); }
142  void disableFlush() { _logBuffer.disableFlush(); }
143  void enableFlush() { _logBuffer.enableFlush(); }
144  void forceFlush() { _logBuffer.pubsync(); }
145  void disableHeader() { _logBuffer.disableHeader(); }
146  void enableHeader() { _logBuffer.enableHeader(); }
147 
149  static LUNCHBOX_API int level;
150 
152  static LUNCHBOX_API unsigned topics;
153 
155  static LUNCHBOX_API Log& instance();
156 
158  static LUNCHBOX_API Log& instance( const char* file, const int line );
159 
161  static LUNCHBOX_API void exit();
162 
164  static LUNCHBOX_API void reset();
165 
167  static std::string& getLogLevelString();
168 
170  static LUNCHBOX_API int getLogLevel( const char* level );
171 
173  static LUNCHBOX_API void setOutput( std::ostream& stream );
174 
176  static LUNCHBOX_API bool setOutput( const std::string& file );
177 
179  static LUNCHBOX_API std::ostream& getOutput ();
180 
189  static LUNCHBOX_API void setClock( Clock* clock );
190 
191  static const Clock& getClock();
192 
194  void setThreadName( const std::string& name )
195  { _logBuffer.setThreadName( name ); }
196 
198  const char* getThreadName() const { return _logBuffer.getThreadName(); }
199 
200  private:
201  LogBuffer _logBuffer;
202 
203  Log( const Log& );
204  Log& operator = ( const Log& );
205 
206  void setLogInfo( const char* file, const int line )
207  { _logBuffer.setLogInfo( file, line ); }
208  };
209 
215  LUNCHBOX_API std::ostream& indent( std::ostream& os );
217  LUNCHBOX_API std::ostream& exdent( std::ostream& os );
218 
220  LUNCHBOX_API std::ostream& disableFlush( std::ostream& os );
222  LUNCHBOX_API std::ostream& enableFlush( std::ostream& os );
224  LUNCHBOX_API std::ostream& forceFlush( std::ostream& os );
225 
227  LUNCHBOX_API std::ostream& disableHeader( std::ostream& os );
229  LUNCHBOX_API std::ostream& enableHeader( std::ostream& os );
230 }
231 
233 #define LBERROR (lunchbox::Log::level >= lunchbox::LOG_ERROR) && \
234  lunchbox::Log::instance( __FILE__, __LINE__ )
235 
236 #define LBWARN (lunchbox::Log::level >= lunchbox::LOG_WARN) && \
237  lunchbox::Log::instance( __FILE__, __LINE__ )
238 
239 #define LBINFO (lunchbox::Log::level >= lunchbox::LOG_INFO) && \
240  lunchbox::Log::instance( __FILE__, __LINE__ )
241 
242 #ifdef NDEBUG
243 # define LBVERB if( false ) \
244  lunchbox::Log::instance( __FILE__, __LINE__ )
245 #else
246 
247 # define LBVERB (lunchbox::Log::level >= lunchbox::LOG_VERB) && \
248  lunchbox::Log::instance( __FILE__, __LINE__ )
249 #endif
250 
255 #define LBLOG(topic) (lunchbox::Log::topics & (topic)) && \
256  lunchbox::Log::instance( __FILE__, __LINE__ )
257 
262 #define LBTHROW(exc) \
263  { \
264  LBLOG(lunchbox::LOG_EXCEPTION) << exc.what() << std::endl; \
265  throw exc; \
266  }
267 
268 #endif //LUNCHBOX_LOG_H