open_toontown_panda3d/dtool/src/prc/notifyCategoryProxy.h

197 lines
7.6 KiB
C++

// Filename: notifyCategoryProxy.h
// Created by: drose (04Mar00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef NOTIFYCATEGORYPROXY_H
#define NOTIFYCATEGORYPROXY_H
#include "dtoolbase.h"
#include "notifyCategory.h"
#include "notifySeverity.h"
#include "pnotify.h"
////////////////////////////////////////////////////////////////////
// Class : NotifyCategoryProxy
// Description : A handy wrapper around a NotifyCategory pointer.
// This wrapper pretends to be a NotifyCategory object
// itself, except that it is capable of initializing its
// pointer if it is NULL.
//
// The advantage to this over a normal pointer is that
// it can be used in functions that run at static init
// time, without worrying about ordering issues among
// static init routines. If the pointer hasn't been
// initialized yet, no sweat; it can initialize itself.
//
// This must be a template class so it can do this
// magic; it templates on a class with a static method
// called get_category() that returns a new pointer to
// the NotifyCategory. This way the compiler can
// generate correct static-init-independent code to
// initialize the proxy.
//
// In general, if the proxy object is treated as if it
// were itself a NotifyCategory object, then it doesn't
// check whether its category is initialized, and so may
// not be run at static init time. That is, you may
// call proxy.info(), but only when you are not running
// at static init time. This is an optimization so you
// can avoid this unnecessary check when you know (as in
// most cases) the code does not run at static init.
//
// On the other hand, if the proxy object is treated as
// if it were a *pointer* to a NotifyCategory object,
// then it *does* check whether its category is
// initialized; you may safely use it in this way at
// static init time. Thus, you may call proxy->info()
// safely whenever you like.
////////////////////////////////////////////////////////////////////
template<class GetCategory>
class NotifyCategoryProxy {
public:
// This should be set to be called at static init time; it
// initializes the pointer if it is not already.
NotifyCategory *init();
// You don't normally need to call these directly, but they're here
// anyway. get_unsafe_ptr() assumes the pointer has been
// initialized; it should be called only when you know static init
// has completed (i.e. in any function that is not executing at
// static init time). get_safe_ptr() should be called when it is
// possible that static init has not yet completed (i.e. in a
// function that might execute at static init time); it calls init()
// first.
INLINE NotifyCategory *get_unsafe_ptr();
INLINE NotifyCategory *get_safe_ptr();
// The following functions, which may be accessed using the
// proxy.function() syntax, call get_unsafe_ptr(). They should be
// used only in non-static-init functions.
INLINE bool is_on(NotifySeverity severity);
#if defined(NOTIFY_DEBUG) || defined(CPPPARSER)
INLINE bool is_spam();
INLINE bool is_debug();
#else
INLINE static bool is_spam();
INLINE static bool is_debug();
#endif
INLINE bool is_info();
INLINE bool is_warning();
INLINE bool is_error();
INLINE bool is_fatal();
INLINE ostream &out(NotifySeverity severity, bool prefix = true);
INLINE ostream &spam(bool prefix = true);
INLINE ostream &debug(bool prefix = true);
INLINE ostream &info(bool prefix = true);
INLINE ostream &warning(bool prefix = true);
INLINE ostream &error(bool prefix = true);
INLINE ostream &fatal(bool prefix = true);
// The same functions as above, when accessed using
// proxy->function() syntax, call get_safe_ptr(). These can be used
// safely either in static-init or non-static-init functions.
INLINE NotifyCategory *operator -> ();
INLINE NotifyCategory &operator * ();
INLINE operator NotifyCategory * ();
private:
NotifyCategory *_ptr;
};
template<class GetCategory>
INLINE ostream &operator << (ostream &out, NotifyCategoryProxy<GetCategory> &proxy) {
return out << proxy->get_fullname();
}
// Finally, here is a set of handy macros to define and reference a
// NotifyCategoryProxy object in each package.
// Following the config convention, this macro defines an external
// reference to a suitable NotifyCategoryProxy object; it should
// appear in the config_*.h file. The proxy object will be named
// basename_cat.
#if defined(WIN32_VC) && !defined(CPPPARSER)
#define NotifyCategoryDecl(basename, expcl, exptp) \
class expcl NotifyCategoryGetCategory_ ## basename { \
public: \
NotifyCategoryGetCategory_ ## basename(); \
static NotifyCategory *get_category(); \
}; \
exptp template class expcl NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename>; \
extern expcl NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat;
#else // WIN32_VC
#define NotifyCategoryDecl(basename, expcl, exptp) \
class NotifyCategoryGetCategory_ ## basename { \
public: \
NotifyCategoryGetCategory_ ## basename(); \
static NotifyCategory *get_category(); \
}; \
extern NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat;
#endif // WIN32_VC
// This macro is the same as the above, except that it declares a category
// that is not intended to be exported from any DLL.
#define NotifyCategoryDeclNoExport(basename) \
class NotifyCategoryGetCategory_ ## basename { \
public: \
NotifyCategoryGetCategory_ ## basename(); \
static NotifyCategory *get_category(); \
}; \
extern NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat;
// This macro defines the actual declaration of the
// NotifyCategoryProxy object defined above; it should appear in the
// config_*.C file. In this macro, parent_category may either be the
// NotifyCategoryProxy object of the parent category
// (e.g. parent_cat), or it may be the quoted fullname of the parent.
#ifdef CPPPARSER
#define NotifyCategoryDefName(basename, actual_name, parent_category)
#define NotifyCategoryDef(basename, parent_category)
#else
#define NotifyCategoryDefName(basename, actual_name, parent_category) \
NotifyCategoryProxy<NotifyCategoryGetCategory_ ## basename> basename ## _cat; \
static NotifyCategoryGetCategory_ ## basename force_init_ ## basename ## _cat; \
NotifyCategoryGetCategory_ ## basename:: \
NotifyCategoryGetCategory_ ## basename() { \
basename ## _cat.init(); \
} \
NotifyCategory *NotifyCategoryGetCategory_ ## basename:: \
get_category() { \
return Notify::ptr()->get_category(string(actual_name), parent_category); \
}
#define NotifyCategoryDef(basename, parent_category) \
NotifyCategoryDefName(basename, #basename, parent_category);
#endif // CPPPARSER
#include "notifyCategoryProxy.I"
#endif