Panda3D
notifyCategoryProxy.h
1 // Filename: notifyCategoryProxy.h
2 // Created by: drose (04Mar00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef NOTIFYCATEGORYPROXY_H
16 #define NOTIFYCATEGORYPROXY_H
17 
18 #include "dtoolbase.h"
19 
20 #include "notifyCategory.h"
21 #include "notifySeverity.h"
22 #include "pnotify.h"
23 
24 ////////////////////////////////////////////////////////////////////
25 // Class : NotifyCategoryProxy
26 // Description : A handy wrapper around a NotifyCategory pointer.
27 // This wrapper pretends to be a NotifyCategory object
28 // itself, except that it is capable of initializing its
29 // pointer if it is NULL.
30 //
31 // The advantage to this over a normal pointer is that
32 // it can be used in functions that run at static init
33 // time, without worrying about ordering issues among
34 // static init routines. If the pointer hasn't been
35 // initialized yet, no sweat; it can initialize itself.
36 //
37 // This must be a template class so it can do this
38 // magic; it templates on a class with a static method
39 // called get_category() that returns a new pointer to
40 // the NotifyCategory. This way the compiler can
41 // generate correct static-init-independent code to
42 // initialize the proxy.
43 //
44 // In general, if the proxy object is treated as if it
45 // were itself a NotifyCategory object, then it doesn't
46 // check whether its category is initialized, and so may
47 // not be run at static init time. That is, you may
48 // call proxy.info(), but only when you are not running
49 // at static init time. This is an optimization so you
50 // can avoid this unnecessary check when you know (as in
51 // most cases) the code does not run at static init.
52 //
53 // On the other hand, if the proxy object is treated as
54 // if it were a *pointer* to a NotifyCategory object,
55 // then it *does* check whether its category is
56 // initialized; you may safely use it in this way at
57 // static init time. Thus, you may call proxy->info()
58 // safely whenever you like.
59 ////////////////////////////////////////////////////////////////////
60 template<class GetCategory>
62 public:
63  // This should be set to be called at static init time; it
64  // initializes the pointer if it is not already.
66 
67  // You don't normally need to call these directly, but they're here
68  // anyway. get_unsafe_ptr() assumes the pointer has been
69  // initialized; it should be called only when you know static init
70  // has completed (i.e. in any function that is not executing at
71  // static init time). get_safe_ptr() should be called when it is
72  // possible that static init has not yet completed (i.e. in a
73  // function that might execute at static init time); it calls init()
74  // first.
76  INLINE NotifyCategory *get_safe_ptr();
77 
78  // The following functions, which may be accessed using the
79  // proxy.function() syntax, call get_unsafe_ptr(). They should be
80  // used only in non-static-init functions.
81 
82  INLINE bool is_on(NotifySeverity severity);
83 
84 #if defined(NOTIFY_DEBUG) || defined(CPPPARSER)
85  INLINE bool is_spam();
86  INLINE bool is_debug();
87 #else
88  CONSTEXPR static bool is_spam();
89  CONSTEXPR static bool is_debug();
90 #endif
91  INLINE bool is_info();
92  INLINE bool is_warning();
93  INLINE bool is_error();
94  INLINE bool is_fatal();
95 
96  INLINE ostream &out(NotifySeverity severity, bool prefix = true);
97  INLINE ostream &spam(bool prefix = true);
98  INLINE ostream &debug(bool prefix = true);
99  INLINE ostream &info(bool prefix = true);
100  INLINE ostream &warning(bool prefix = true);
101  INLINE ostream &error(bool prefix = true);
102  INLINE ostream &fatal(bool prefix = true);
103 
104  // The same functions as above, when accessed using
105  // proxy->function() syntax, call get_safe_ptr(). These can be used
106  // safely either in static-init or non-static-init functions.
107  INLINE NotifyCategory *operator -> ();
108  INLINE NotifyCategory &operator * ();
109  INLINE operator NotifyCategory * ();
110 
111 private:
112  NotifyCategory *_ptr;
113 };
114 
115 template<class GetCategory>
116 INLINE ostream &operator << (ostream &out, NotifyCategoryProxy<GetCategory> &proxy) {
117  return out << proxy->get_fullname();
118 }
119 
120 // Finally, here is a set of handy macros to define and reference a
121 // NotifyCategoryProxy object in each package.
122 
123 // Following the config convention, this macro defines an external
124 // reference to a suitable NotifyCategoryProxy object; it should
125 // appear in the config_*.h file. The proxy object will be named
126 // basename_cat.
127 
128 #if defined(WIN32_VC) && !defined(CPPPARSER)
129 
130 #define NotifyCategoryDecl(basename, expcl, exptp) \
131  class expcl NotifyCategoryGetCategory_ ## basename { \
132  public: \
133  NotifyCategoryGetCategory_ ## basename(); \
134  static NotifyCategory *get_category(); \
135  }; \
136  exptp template class expcl NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename>; \
137  extern expcl NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat;
138 
139 #else // WIN32_VC
140 
141 #define NotifyCategoryDecl(basename, expcl, exptp) \
142  class NotifyCategoryGetCategory_ ## basename { \
143  public: \
144  NotifyCategoryGetCategory_ ## basename(); \
145  static NotifyCategory *get_category(); \
146  }; \
147  extern NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat;
148 
149 #endif // WIN32_VC
150 
151 // This macro is the same as the above, except that it declares a category
152 // that is not intended to be exported from any DLL.
153 
154 #define NotifyCategoryDeclNoExport(basename) \
155  class NotifyCategoryGetCategory_ ## basename { \
156  public: \
157  NotifyCategoryGetCategory_ ## basename(); \
158  static NotifyCategory *get_category(); \
159  }; \
160  extern NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat;
161 
162 // This macro defines the actual declaration of the
163 // NotifyCategoryProxy object defined above; it should appear in the
164 // config_*.C file. In this macro, parent_category may either be the
165 // NotifyCategoryProxy object of the parent category
166 // (e.g. parent_cat), or it may be the quoted fullname of the parent.
167 
168 #ifdef CPPPARSER
169 #define NotifyCategoryDefName(basename, actual_name, parent_category)
170 #define NotifyCategoryDef(basename, parent_category)
171 
172 #else
173 #define NotifyCategoryDefName(basename, actual_name, parent_category) \
174  NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat; \
175  static NotifyCategoryGetCategory_ ## basename force_init_ ## basename ## _cat; \
176  NotifyCategoryGetCategory_ ## basename:: \
177  NotifyCategoryGetCategory_ ## basename() { \
178  basename ## _cat.init(); \
179  } \
180  NotifyCategory *NotifyCategoryGetCategory_ ## basename:: \
181  get_category() { \
182  return Notify::ptr()->get_category(string(actual_name), parent_category); \
183  }
184 #define NotifyCategoryDef(basename, parent_category) \
185  NotifyCategoryDefName(basename, #basename, parent_category);
186 
187 #endif // CPPPARSER
188 
189 
190 #include "notifyCategoryProxy.I"
191 
192 #endif
NotifyCategory & operator*()
This operator handles the case of dereferencing the proxy object as if it were a pointer, e.g.
NotifyCategory * get_unsafe_ptr()
Returns a pointer which is assumed to have been already initialized.
A handy wrapper around a NotifyCategory pointer.
A particular category of error messages.
NotifyCategory * operator->()
This magic operator function defines the syntax proxy->info(), etc., for all of the methods that are ...
NotifyCategory * get_safe_ptr()
Returns a pointer which is *not* assumed to have been already initialized; if necessary, it will be initialized before it returns.
NotifyCategory * init()
Initializes the proxy object by calling get_category() on the template class.