Shadowrun: Awakened 29 September 2011 - Build 871
Logging.hpp
Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2009-2010 Christopher A. Taylor.  All rights reserved.
00003 
00004     Redistribution and use in source and binary forms, with or without
00005     modification, are permitted provided that the following conditions are met:
00006 
00007     * Redistributions of source code must retain the above copyright notice,
00008       this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice,
00010       this list of conditions and the following disclaimer in the documentation
00011       and/or other materials provided with the distribution.
00012     * Neither the name of LibCat nor the names of its contributors may be used
00013       to endorse or promote products derived from this software without
00014       specific prior written permission.
00015 
00016     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00020     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00021     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00022     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00025     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026     POSSIBILITY OF SUCH DAMAGE.
00027 */
00028 
00029 #ifndef CAT_LOGGING_HPP
00030 #define CAT_LOGGING_HPP
00031 
00032 #include <cat/threads/RegionAllocator.hpp>
00033 
00034 #if defined(CAT_OS_WINDOWS)
00035 #include <cat/port/WindowsInclude.hpp>
00036 #endif
00037 
00038 namespace cat {
00039 
00040 
00042 
00043 enum EventSeverity
00044 {
00045     LVL_INANE,
00046     LVL_INFO,
00047     LVL_WARN,
00048     LVL_OOPS,
00049     LVL_FATAL,
00050 
00051     LVL_SILENT, // invalid for an actual event's level, valid value for a threshold
00052 };
00053 
00054 
00056 
00057 region_string HexDumpString(const void *vdata, u32 bytes);
00058 
00059 // Write to console (and debug log in windows) then trigger a breakpoint and exit
00060 void FatalStop(const char *message);
00061 
00062 void DefaultLogCallback(EventSeverity severity, const char *source, region_ostringstream &msg);
00063 
00064 
00066 
00067 typedef void (*LogCallback)(EventSeverity severity, const char *source, region_ostringstream &msg);
00068 
00069 class Logging : public Singleton<Logging>
00070 {
00071     CAT_SINGLETON(Logging);
00072 
00073     LogCallback _callback;
00074 
00075     friend class Recorder;
00076     void LogEvent(Recorder *recorder);
00077 
00078 public:
00079     int _log_threshold;
00080 
00081 public:
00082     void Initialize(EventSeverity min_severity = LVL_INANE);
00083     CAT_INLINE void SetThreshold(EventSeverity min_severity) { _log_threshold = min_severity; }
00084     void ReadSettings();
00085     void Shutdown();
00086 
00087 protected:
00088     bool _service;
00089 #if defined(CAT_OS_WINDOWS)
00090     HANDLE _event_source;
00091 #endif
00092 
00093 public:
00094     CAT_INLINE bool IsService() { return _service; }
00095     void EnableServiceMode(const char *service_name);
00096     void WriteServiceLog(EventSeverity severity, const char *line);
00097 
00098 public:
00099     // Not thread-safe
00100     CAT_INLINE void SetLogCallback(LogCallback cb) { _callback = cb; }
00101 };
00102 
00103 
00105 
00106 class Recorder
00107 {
00108     friend class Logging;
00109     EventSeverity _severity;
00110     const char *_subsystem;
00111     region_ostringstream _msg;
00112 
00113 public:
00114     Recorder(const char *subsystem, EventSeverity severity);
00115     ~Recorder();
00116 
00117 public:
00118     template<class T> inline Recorder &operator<<(const T &t)
00119     {
00120         _msg << t;
00121         return *this;
00122     }
00123 };
00124 
00125 // Because there is an IF statement in the macro, you cannot use the
00126 // braceless if-else construction:
00127 //  if (XYZ) WARN("SS") << "ERROR!"; else INFO("SS") << "OK!";       <-- bad
00128 // Instead use:
00129 //  if (XYZ) { WARN("SS") << "ERROR!"; } else INFO("SS") << "OK!";   <-- good
00130 #define RECORD(subsystem, severity) \
00131     if (severity >= Logging::ii->_log_threshold) Recorder(subsystem, severity)
00132 
00133 #define INANE(subsystem)    RECORD(subsystem, LVL_INANE)
00134 #define INFO(subsystem)     RECORD(subsystem, LVL_INFO)
00135 #define WARN(subsystem)     RECORD(subsystem, LVL_WARN)
00136 #define OOPS(subsystem)     RECORD(subsystem, LVL_OOPS)
00137 #define FATAL(subsystem)    RECORD(subsystem, LVL_FATAL)
00138 
00139 
00141 
00142 class Enforcer
00143 {
00144 protected:
00145     std::ostringstream oss;
00146 
00147 public:
00148     Enforcer(const char *locus);
00149     ~Enforcer();
00150 
00151 public:
00152     template<class T> inline Enforcer &operator<<(const T &t)
00153     {
00154         oss << t;
00155         return *this;
00156     }
00157 };
00158 
00159 
00160 #define USE_ENFORCE_EXPRESSION_STRING
00161 #define USE_ENFORCE_FILE_LINE_STRING
00162 
00163 
00164 #if defined(USE_ENFORCE_EXPRESSION_STRING)
00165 # define ENFORCE_EXPRESSION_STRING(exp) "Failed assertion (" #exp ")"
00166 #else
00167 # define ENFORCE_EXPRESSION_STRING(exp) "Failed assertion"
00168 #endif
00169 
00170 #if defined(USE_ENFORCE_FILE_LINE_STRING)
00171 # define ENFORCE_FILE_LINE_STRING " at " __FILE__ ":" CAT_STRINGIZE(__LINE__)
00172 #else
00173 # define ENFORCE_FILE_LINE_STRING ""
00174 #endif
00175 
00176 // Because there is an IF statement in the macro, you cannot use the
00177 // braceless if-else construction:
00178 //  if (XYZ) ENFORCE(A == B) << "ERROR"; else INFO("SS") << "OK";       <-- bad!
00179 // Instead use:
00180 //  if (XYZ) { ENFORCE(A == B) << "ERROR"; } else INFO("SS") << "OK";   <-- good!
00181 
00182 #define ENFORCE(exp) if ( (exp) == 0 ) Enforcer(ENFORCE_EXPRESSION_STRING(exp) ENFORCE_FILE_LINE_STRING "\n")
00183 #define EXCEPTION() Enforcer("Exception" ENFORCE_FILE_LINE_STRING "\n")
00184 
00185 #if defined(CAT_DEBUG)
00186 # define DEBUG_ENFORCE(exp) ENFORCE(exp)
00187 #else
00188 # define DEBUG_ENFORCE(exp) if (0) ENFORCE(exp) /* hopefully will be optimized out of existence */
00189 #endif
00190 
00191 
00192 } // namespace cat
00193 
00194 #endif // CAT_LOGGING_HPP

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net