dlvhex
2.5.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005-2007 Roman Schindlauer 00003 * Copyright (C) 2006-2015 Thomas Krennwallner 00004 * Copyright (C) 2009-2016 Peter Schüller 00005 * Copyright (C) 2011-2016 Christoph Redl 00006 * Copyright (C) 2015-2016 Tobias Kaminski 00007 * Copyright (C) 2015-2016 Antonius Weinzierl 00008 * 00009 * This file is part of dlvhex. 00010 * 00011 * dlvhex is free software; you can redistribute it and/or modify it 00012 * under the terms of the GNU Lesser General Public License as 00013 * published by the Free Software Foundation; either version 2.1 of 00014 * the License, or (at your option) any later version. 00015 * 00016 * dlvhex is distributed in the hope that it will be useful, but 00017 * WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with dlvhex; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00024 * 02110-1301 USA. 00025 */ 00026 00034 #ifndef LOGGER_HPP_INCLUDED__17092010 00035 #define LOGGER_HPP_INCLUDED__17092010 00036 00037 #ifdef HAVE_CONFIG_H 00038 #include "config.h" 00039 #endif 00040 00041 #include "dlvhex2/PlatformDefinitions.h" 00042 00043 #include <boost/preprocessor/cat.hpp> 00044 #include <boost/optional.hpp> 00045 #include <boost/cstdint.hpp> 00046 00047 #include <boost/thread/mutex.hpp> 00048 #include <boost/thread/tss.hpp> 00049 00050 #ifndef NDEBUG 00051 # define LOG_SCOPED_LOCK(varname) boost::mutex::scoped_lock varname(Logger::Mutex()); 00052 #else 00053 # define LOG_SCOPED_LOCK(varname) do { } while(false) 00054 #endif 00055 00056 #include <iostream> 00057 #include <iomanip> 00058 #include <sstream> 00059 00061 class DLVHEX_EXPORT Logger 00062 { 00063 public: 00066 typedef uint32_t Levels; 00068 static const Levels DBG = 0x01; 00070 static const Levels INFO = 0x02; 00072 static const Levels WARNING = 0x04; 00074 static const Levels ERROR = 0x08; 00075 00076 // this is now very dlvhex-specific 00078 static const Levels PLUGIN = 0x10; 00080 static const Levels ANALYZE = 0x20; 00082 static const Levels MODELB = 0x40; 00084 static const Levels STATS = 0x80; 00085 00086 private: 00088 std::ostream& out; 00090 boost::thread_specific_ptr<std::string> indent; 00092 Levels printlevels; 00094 int levelwidth; 00095 00096 private: 00102 Logger(): 00103 out(std::cerr), printlevels(~static_cast<Levels>(0)), levelwidth(1) {} 00104 00106 ~Logger() { 00107 stream() << std::endl; 00108 startline(DBG); 00109 #ifndef NDEBUG 00110 stream() << "clean exit!" << std::endl; 00111 #endif 00112 } 00113 00114 public: 00117 static Logger& Instance(); 00120 static boost::mutex& Mutex(); 00121 00124 inline std::ostream& stream() 00125 { return out; } 00126 00129 void setPrintLevels(Levels levels); 00132 void setPrintLevelWidth(int width); 00135 Levels getPrintLevels() const; 00136 00141 inline void startline(Levels forlevel) { 00142 if (!indent.get()) indent.reset(new std::string("")); 00143 if( levelwidth == 0 ) { 00144 out << *indent; 00145 } 00146 else { 00147 out << std::hex << std::setw(levelwidth) << forlevel << std::dec << " " << *indent; 00148 } 00149 } 00150 00154 inline bool shallPrint(Levels forlevel) 00155 { return (printlevels & forlevel) != 0; } 00156 00157 friend class Closure; 00159 class Closure 00160 { 00161 private: 00163 Logger& l; 00165 Levels level; 00167 unsigned cutoff; 00169 bool message; 00170 00172 inline void sayHello() { 00173 // hello message 00174 if( message ) { 00175 l.startline(level); 00176 l.stream() << "ENTRY" << std::endl; 00177 } 00178 } 00179 00181 inline void sayGoodbye() { 00182 // goodbye message 00183 if( message ) { 00184 l.startline(level); 00185 l.stream() << "EXIT" << std::endl; 00186 } 00187 } 00188 00189 public: 00197 Closure(Logger& l, Levels level, const std::string& str, bool message): 00198 l(l), level(level), message(message) { 00199 if (!l.indent.get()) l.indent.reset(new std::string("")); 00200 cutoff = l.indent->size(); 00201 00202 if( l.shallPrint(level) ) { 00203 LOG_SCOPED_LOCK(lock); 00204 *l.indent += str + " "; 00205 sayHello(); 00206 } 00207 } 00208 00217 Closure(Logger& l, Levels level, const std::string& str, const void* const val, bool message): 00218 l(l), level(level), message(message) { 00219 if (!l.indent.get()) l.indent.reset(new std::string("")); 00220 cutoff = l.indent->size(); 00221 00222 if( l.shallPrint(level) ) { 00223 LOG_SCOPED_LOCK(lock); 00224 std::stringstream ss; 00225 ss << str << "/" << val << " "; 00226 *l.indent += ss.str(); 00227 sayHello(); 00228 } 00229 } 00230 00232 ~Closure() { 00233 if (!l.indent.get()) l.indent.reset(new std::string("")); 00234 if( l.shallPrint(level) ) { 00235 LOG_SCOPED_LOCK(lock); 00236 sayGoodbye(); 00237 // restore indentation level 00238 l.indent->erase(cutoff); 00239 } 00240 } 00241 }; 00242 00244 class Init 00245 { 00246 public: 00249 Init(Levels levels) { 00250 Logger::Instance().setPrintLevels(levels); 00251 } 00252 }; 00253 }; 00254 00255 // the following will always be realized 00256 //#ifndef NDEBUG 00257 # define LOG(level,streamout) do { LOG_SCOPED_LOCK(lock); \ 00258 if( Logger::Instance().shallPrint(Logger:: level) ) \ 00259 { \ 00260 Logger::Instance().startline(Logger:: level); \ 00261 Logger::Instance().stream() << streamout << std::endl; \ 00262 } \ 00263 } while(false); 00264 # define LOG_CLOSURE_ID BOOST_PP_CAT(log_closure_,__LINE__) 00265 # define LOG_INDENT(level) Logger::Closure LOG_CLOSURE_ID (Logger::Instance(), Logger:: level, " ", false) 00266 # define LOG_SCOPE(level,name,msg) Logger::Closure LOG_CLOSURE_ID (Logger::Instance(), Logger:: level, name, msg) 00267 # define LOG_VSCOPE(level,name,val,msg) Logger::Closure LOG_CLOSURE_ID (Logger::Instance(), Logger:: level, name, reinterpret_cast<const void* const>(val), msg) 00268 /* 00269 #else 00270 # define LOG(level,streamout) do { } while(false) 00271 # define LOG_CLOSURE_ID BOOST_PP_CAT(log_closure_,__LINE__) do { } while(false) 00272 # define LOG_INDENT(level) do { } while(false) 00273 # define LOG_SCOPE(level,name,msg) do { } while(false) 00274 # define LOG_VSCOPE(level,name,val,msg) do { } while(false) 00275 #endif 00276 */ 00277 00278 # define LOG_INIT(setlevel) namespace { Logger::Init LOG_CLOSURE_ID (setlevel); } 00279 00280 // the following are debug-flag dependant 00281 #ifndef NDEBUG 00282 # define DBGLOG(level,streamout) LOG(level,streamout) 00283 # define DBGLOG_INDENT(level) LOG_INDENT(level) 00284 # define DBGLOG_SCOPE(level,name,msg) LOG_SCOPE(level,name,msg) 00285 # define DBGLOG_VSCOPE(level,name,val,msg) LOG_VSCOPE(level,name,val,msg) 00286 #else 00287 # define DBGLOG(level,streamout) do { } while(false) 00288 # define DBGLOG_INDENT(level) do { } while(false) 00289 # define DBGLOG_SCOPE(level,name,msg) do { } while(false) 00290 # define DBGLOG_VSCOPE(level,name,val,msg) do { } while(false) 00291 #endif 00292 #endif // LOGGER_HPP_INCLUDED__17092010 00293 00294 // vim:expandtab:ts=4:sw=4: 00295 // mode: C++ 00296 // End: