llerror.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:10k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llerror.h
  3.  * @date   December 2006
  4.  * @brief error message system
  5.  *
  6.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  7.  * 
  8.  * Copyright (c) 2006-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #ifndef LL_LLERROR_H
  34. #define LL_LLERROR_H
  35. #include <sstream>
  36. #include <typeinfo>
  37. #include "llerrorlegacy.h"
  38. #include "stdtypes.h"
  39. /* Error Logging Facility
  40. Information for most users:
  41. Code can log messages with constuctions like this:
  42. LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id
  43. << " denied due to timeout" << LL_ENDL;
  44. Messages can be logged to one of four increasing levels of concern,
  45. using one of four "streams":
  46. LL_DEBUGS("StringTag") - debug messages that are normally supressed
  47. LL_INFOS("StringTag") - informational messages that are normall shown
  48. LL_WARNS("StringTag") - warning messages that singal a problem
  49. LL_ERRS("StringTag") - error messages that are major, unrecoverable failures
  50. The later (LL_ERRS("StringTag")) automatically crashes the process after the message
  51. is logged.
  52. Note that these "streams" are actually #define magic.  Rules for use:
  53. * they cannot be used as normal streams, only to start a message
  54. * messages written to them MUST be terminated with LL_ENDL
  55. * between the opening and closing, the << operator is indeed
  56.   writing onto a std::ostream, so all conversions and stream
  57.   formating are available
  58. These messages are automatically logged with function name, and (if enabled)
  59. file and line of the message.  (Note: Existing messages that already include
  60. the function name don't get name printed twice.)
  61. If you have a class, adding LOG_CLASS line to the declaration will cause
  62. all messages emitted from member functions (normal and static) to be tagged
  63. with the proper class name as well as the function name:
  64. class LLFoo
  65. {
  66. LOG_CLASS(LLFoo);
  67. public:
  68. ...
  69. };
  70. void LLFoo::doSomething(int i)
  71. {
  72. if (i > 100)
  73. {
  74. LL_WARNS("FooBarTag") << "called with a big value for i: " << i << LL_ENDL; 
  75. }
  76. ...
  77. }
  78. will result in messages like:
  79. WARN: LLFoo::doSomething: called with a big value for i: 283
  80. Which messages are logged and which are supressed can be controled at run
  81. time from the live file logcontrol.xml based on function, class and/or 
  82. source file.  See etc/logcontrol-dev.xml for details.
  83. Lastly, logging is now very efficient in both compiled code and execution
  84. when skipped.  There is no need to wrap messages, even debugging ones, in
  85. #ifdef _DEBUG constructs.  LL_DEBUGS("StringTag") messages are compiled into all builds,
  86. even release.  Which means you can use them to help debug even when deployed
  87. to a real grid.
  88. */
  89. namespace LLError
  90. {
  91. enum ELevel
  92. {
  93. LEVEL_ALL = 0,
  94. // used to indicate that all messagess should be logged
  95. LEVEL_DEBUG = 0,
  96. LEVEL_INFO = 1,
  97. LEVEL_WARN = 2,
  98. LEVEL_ERROR = 3, // used to be called FATAL
  99. LEVEL_NONE = 4
  100. // not really a level
  101. // used to indicate that no messages should be logged
  102. };
  103. /* Macro support
  104. The classes CallSite and Log are used by the logging macros below.
  105. They are not intended for general use.
  106. */
  107. class CallSite;
  108. class LL_COMMON_API Log
  109. {
  110. public:
  111. static bool shouldLog(CallSite&);
  112. static std::ostringstream* out();
  113. static void flush(std::ostringstream* out, char* message)  ;
  114. static void flush(std::ostringstream*, const CallSite&);
  115. };
  116. class LL_COMMON_API CallSite
  117. {
  118. // Represents a specific place in the code where a message is logged
  119. // This is public because it is used by the macros below.  It is not
  120. // intended for public use.
  121. public:
  122. CallSite(ELevel, const char* file, int line,
  123. const std::type_info& class_info, const char* function, const char* broadTag, const char* narrowTag, bool printOnce);
  124. bool shouldLog()
  125. { return mCached ? mShouldLog : Log::shouldLog(*this); }
  126. // this member function needs to be in-line for efficiency
  127. void invalidate();
  128. private:
  129. // these describe the call site and never change
  130. const ELevel mLevel;
  131. const char* const mFile;
  132. const int mLine;
  133. const std::type_info&    mClassInfo;
  134. const char* const mFunction;
  135. const char* const mBroadTag;
  136. const char* const mNarrowTag;
  137. const bool mPrintOnce;
  138. // these implement a cache of the call to shouldLog()
  139. bool mCached;
  140. bool mShouldLog;
  141. friend class Log;
  142. };
  143. class End { };
  144. inline std::ostream& operator<<(std::ostream& s, const End&)
  145. { return s; }
  146. // used to indicate the end of a message
  147. class NoClassInfo { };
  148. // used to indicate no class info known for logging
  149.    //LLCallStacks keeps track of call stacks and output the call stacks to log file
  150.    //when LLAppViewer::handleViewerCrash() is triggered.
  151.    //
  152.    //Note: to be simple, efficient and necessary to keep track of correct call stacks, 
  153. //LLCallStacks is designed not to be thread-safe.
  154.    //so try not to use it in multiple parallel threads at same time.
  155.    //Used in a single thread at a time is fine.
  156.    class LL_COMMON_API LLCallStacks
  157.    {
  158.    private:
  159.        static char**  sBuffer ;
  160.    static S32     sIndex ;
  161.           
  162.    public:   
  163.    static void push(const char* function, const int line) ;
  164.    static std::ostringstream* insert(const char* function, const int line) ;
  165.        static void print() ;
  166.        static void clear() ;
  167.    static void end(std::ostringstream* _out) ;
  168.    }; 
  169. }
  170. //this is cheaper than llcallstacks if no need to output other variables to call stacks. 
  171. #define llpushcallstacks LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
  172. #define llcallstacks 
  173. {
  174.        std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; 
  175.        (*_out)
  176. #define llcallstacksendl 
  177. LLError::End(); 
  178. LLError::LLCallStacks::end(_out) ; 
  179. }
  180. #define llclearcallstacks LLError::LLCallStacks::clear()
  181. #define llprintcallstacks LLError::LLCallStacks::print() 
  182. /*
  183. Class type information for logging
  184.  */
  185. #define LOG_CLASS(s) typedef s _LL_CLASS_TO_LOG
  186. // Declares class to tag logged messages with.
  187. // See top of file for example of how to use this
  188. typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
  189. // Outside a class declartion, or in class without LOG_CLASS(), this
  190. // typedef causes the messages to not be associated with any class.
  191. /*
  192. Error Logging Macros
  193. See top of file for common usage.
  194. */
  195. #define lllog(level, broadTag, narrowTag, once) 
  196. do { 
  197. static LLError::CallSite _site( 
  198. level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);
  199. if (LL_UNLIKELY(_site.shouldLog()))
  200. std::ostringstream* _out = LLError::Log::out(); 
  201. (*_out)
  202. // DEPRECATED: Don't call directly, use LL_ENDL instead, which actually looks like a macro
  203. #define llendl 
  204. LLError::End(); 
  205. LLError::Log::flush(_out, _site); 
  206. } while(0)
  207. // DEPRECATED: Use the new macros that allow tags and *look* like macros.
  208. #define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false)
  209. #define llinfos lllog(LLError::LEVEL_INFO, NULL, NULL, false)
  210. #define llwarns lllog(LLError::LEVEL_WARN, NULL, NULL, false)
  211. #define llerrs lllog(LLError::LEVEL_ERROR, NULL, NULL, false)
  212. #define llcont (*_out)
  213. // NEW Macros for debugging, allow the passing of a string tag
  214. // One Tag
  215. #define LL_DEBUGS(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, false)
  216. #define LL_INFOS(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, false)
  217. #define LL_WARNS(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, false)
  218. #define LL_ERRS(broadTag) lllog(LLError::LEVEL_ERROR, broadTag, NULL, false)
  219. // Two Tags
  220. #define LL_DEBUGS2(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, false)
  221. #define LL_INFOS2(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, false)
  222. #define LL_WARNS2(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, false)
  223. #define LL_ERRS2(broadTag, narrowTag) lllog(LLError::LEVEL_ERROR, broadTag, narrowTag, false)
  224. // Only print the log message once (good for warnings or infos that would otherwise
  225. // spam the log file over and over, such as tighter loops).
  226. #define LL_DEBUGS_ONCE(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, true)
  227. #define LL_INFOS_ONCE(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, true)
  228. #define LL_WARNS_ONCE(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, true)
  229. #define LL_DEBUGS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, true)
  230. #define LL_INFOS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, true)
  231. #define LL_WARNS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, true)
  232. #define LL_ENDL llendl
  233. #define LL_CONT (*_out)
  234. /*
  235. Use this construct if you need to do computation in the middle of a
  236. message:
  237. LL_INFOS("AgentGesture") << "the agent " << agend_id;
  238. switch (f)
  239. {
  240. case FOP_SHRUGS: LL_CONT << "shrugs"; break;
  241. case FOP_TAPS: LL_CONT << "points at " << who; break;
  242. case FOP_SAYS: LL_CONT << "says " << message; break;
  243. }
  244. LL_CONT << " for " << t << " seconds" << LL_ENDL;
  245. Such computation is done iff the message will be logged.
  246. */
  247. #endif // LL_LLERROR_H