Panda3D
 All Classes Functions Variables Enumerations
notifyCategoryProxy.h
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
 All Classes Functions Variables Enumerations