Panda3D
|
00001 // Filename: notifyCategoryProxy.h 00002 // Created by: drose (04Mar00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef NOTIFYCATEGORYPROXY_H 00016 #define NOTIFYCATEGORYPROXY_H 00017 00018 #include "dtoolbase.h" 00019 00020 #include "notifyCategory.h" 00021 #include "notifySeverity.h" 00022 #include "pnotify.h" 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Class : NotifyCategoryProxy 00026 // Description : A handy wrapper around a NotifyCategory pointer. 00027 // This wrapper pretends to be a NotifyCategory object 00028 // itself, except that it is capable of initializing its 00029 // pointer if it is NULL. 00030 // 00031 // The advantage to this over a normal pointer is that 00032 // it can be used in functions that run at static init 00033 // time, without worrying about ordering issues among 00034 // static init routines. If the pointer hasn't been 00035 // initialized yet, no sweat; it can initialize itself. 00036 // 00037 // This must be a template class so it can do this 00038 // magic; it templates on a class with a static method 00039 // called get_category() that returns a new pointer to 00040 // the NotifyCategory. This way the compiler can 00041 // generate correct static-init-independent code to 00042 // initialize the proxy. 00043 // 00044 // In general, if the proxy object is treated as if it 00045 // were itself a NotifyCategory object, then it doesn't 00046 // check whether its category is initialized, and so may 00047 // not be run at static init time. That is, you may 00048 // call proxy.info(), but only when you are not running 00049 // at static init time. This is an optimization so you 00050 // can avoid this unnecessary check when you know (as in 00051 // most cases) the code does not run at static init. 00052 // 00053 // On the other hand, if the proxy object is treated as 00054 // if it were a *pointer* to a NotifyCategory object, 00055 // then it *does* check whether its category is 00056 // initialized; you may safely use it in this way at 00057 // static init time. Thus, you may call proxy->info() 00058 // safely whenever you like. 00059 //////////////////////////////////////////////////////////////////// 00060 template<class GetCategory> 00061 class NotifyCategoryProxy { 00062 public: 00063 // This should be set to be called at static init time; it 00064 // initializes the pointer if it is not already. 00065 NotifyCategory *init(); 00066 00067 // You don't normally need to call these directly, but they're here 00068 // anyway. get_unsafe_ptr() assumes the pointer has been 00069 // initialized; it should be called only when you know static init 00070 // has completed (i.e. in any function that is not executing at 00071 // static init time). get_safe_ptr() should be called when it is 00072 // possible that static init has not yet completed (i.e. in a 00073 // function that might execute at static init time); it calls init() 00074 // first. 00075 INLINE NotifyCategory *get_unsafe_ptr(); 00076 INLINE NotifyCategory *get_safe_ptr(); 00077 00078 // The following functions, which may be accessed using the 00079 // proxy.function() syntax, call get_unsafe_ptr(). They should be 00080 // used only in non-static-init functions. 00081 00082 INLINE bool is_on(NotifySeverity severity); 00083 00084 #if defined(NOTIFY_DEBUG) || defined(CPPPARSER) 00085 INLINE bool is_spam(); 00086 INLINE bool is_debug(); 00087 #else 00088 INLINE static bool is_spam(); 00089 INLINE static bool is_debug(); 00090 #endif 00091 INLINE bool is_info(); 00092 INLINE bool is_warning(); 00093 INLINE bool is_error(); 00094 INLINE bool is_fatal(); 00095 00096 INLINE ostream &out(NotifySeverity severity, bool prefix = true); 00097 INLINE ostream &spam(bool prefix = true); 00098 INLINE ostream &debug(bool prefix = true); 00099 INLINE ostream &info(bool prefix = true); 00100 INLINE ostream &warning(bool prefix = true); 00101 INLINE ostream &error(bool prefix = true); 00102 INLINE ostream &fatal(bool prefix = true); 00103 00104 // The same functions as above, when accessed using 00105 // proxy->function() syntax, call get_safe_ptr(). These can be used 00106 // safely either in static-init or non-static-init functions. 00107 INLINE NotifyCategory *operator -> (); 00108 INLINE NotifyCategory &operator * (); 00109 INLINE operator NotifyCategory * (); 00110 00111 private: 00112 NotifyCategory *_ptr; 00113 }; 00114 00115 template<class GetCategory> 00116 INLINE ostream &operator << (ostream &out, NotifyCategoryProxy<GetCategory> &proxy) { 00117 return out << proxy->get_fullname(); 00118 } 00119 00120 // Finally, here is a set of handy macros to define and reference a 00121 // NotifyCategoryProxy object in each package. 00122 00123 // Following the config convention, this macro defines an external 00124 // reference to a suitable NotifyCategoryProxy object; it should 00125 // appear in the config_*.h file. The proxy object will be named 00126 // basename_cat. 00127 00128 #if defined(WIN32_VC) && !defined(CPPPARSER) 00129 00130 #define NotifyCategoryDecl(basename, expcl, exptp) \ 00131 class expcl NotifyCategoryGetCategory_ ## basename { \ 00132 public: \ 00133 NotifyCategoryGetCategory_ ## basename(); \ 00134 static NotifyCategory *get_category(); \ 00135 }; \ 00136 exptp template class expcl NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename>; \ 00137 extern expcl NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat; 00138 00139 #else // WIN32_VC 00140 00141 #define NotifyCategoryDecl(basename, expcl, exptp) \ 00142 class NotifyCategoryGetCategory_ ## basename { \ 00143 public: \ 00144 NotifyCategoryGetCategory_ ## basename(); \ 00145 static NotifyCategory *get_category(); \ 00146 }; \ 00147 extern NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat; 00148 00149 #endif // WIN32_VC 00150 00151 // This macro is the same as the above, except that it declares a category 00152 // that is not intended to be exported from any DLL. 00153 00154 #define NotifyCategoryDeclNoExport(basename) \ 00155 class NotifyCategoryGetCategory_ ## basename { \ 00156 public: \ 00157 NotifyCategoryGetCategory_ ## basename(); \ 00158 static NotifyCategory *get_category(); \ 00159 }; \ 00160 extern NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat; 00161 00162 // This macro defines the actual declaration of the 00163 // NotifyCategoryProxy object defined above; it should appear in the 00164 // config_*.C file. In this macro, parent_category may either be the 00165 // NotifyCategoryProxy object of the parent category 00166 // (e.g. parent_cat), or it may be the quoted fullname of the parent. 00167 00168 #ifdef CPPPARSER 00169 #define NotifyCategoryDefName(basename, actual_name, parent_category) 00170 #define NotifyCategoryDef(basename, parent_category) 00171 00172 #else 00173 #define NotifyCategoryDefName(basename, actual_name, parent_category) \ 00174 NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat; \ 00175 static NotifyCategoryGetCategory_ ## basename force_init_ ## basename ## _cat; \ 00176 NotifyCategoryGetCategory_ ## basename:: \ 00177 NotifyCategoryGetCategory_ ## basename() { \ 00178 basename ## _cat.init(); \ 00179 } \ 00180 NotifyCategory *NotifyCategoryGetCategory_ ## basename:: \ 00181 get_category() { \ 00182 return Notify::ptr()->get_category(string(actual_name), parent_category); \ 00183 } 00184 #define NotifyCategoryDef(basename, parent_category) \ 00185 NotifyCategoryDefName(basename, #basename, parent_category); 00186 00187 #endif // CPPPARSER 00188 00189 00190 #include "notifyCategoryProxy.I" 00191 00192 #endif