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