/** * PANDA 3D SOFTWARE * Copyright (c) Carnegie Mellon University. All rights reserved. * * All use of this software is subject to the terms of the revised BSD * license. You should have received a copy of this license along * with this source code in a file named "LICENSE." * * @file dtoolbase_cc.h * @author drose * @date 2000-09-13 */ #ifndef DTOOLBASE_CC_H #define DTOOLBASE_CC_H // This file should never be included directly; it's intended to be included // only from dtoolbase.h. Include that file instead. #ifdef __cplusplus #ifdef USE_TAU // Tau provides this destructive version of stdbool.h that we must mask. #define __PDT_STDBOOL_H_ #endif #ifdef CPPPARSER #include #include using namespace std; #define INLINE inline #define ALWAYS_INLINE inline #define TYPENAME typename #define CONSTEXPR constexpr #define ALWAYS_INLINE_CONSTEXPR constexpr #define NOEXCEPT noexcept #define FINAL final #define MOVE(x) x #define DEFAULT_CTOR = default #define DEFAULT_DTOR = default #define DEFAULT_ASSIGN = default #define DELETED = delete #define DELETED_ASSIGN = delete #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname) // We define the macro PUBLISHED to mark C++ methods that are to be published // via interrogate to scripting languages. However, if we're not running the // interrogate pass (CPPPARSER isn't defined), this maps to public. #define PUBLISHED __published typedef int ios_openmode; typedef int ios_fmtflags; typedef int ios_iostate; typedef int ios_seekdir; #else // CPPPARSER #ifdef PHAVE_IOSTREAM #include #include #include #else #include #include #include #endif #ifdef PHAVE_SSTREAM #include #else #include "fakestringstream.h" #endif #ifdef PHAVE_NEW #include #endif #include #include #ifdef HAVE_NAMESPACE using namespace std; #endif #ifdef HAVE_TYPENAME #define TYPENAME typename #else #define TYPENAME #endif #ifndef HAVE_WCHAR_T // Some C++ libraries (os x 3.1) don't define this. typedef unsigned short wchar_t; #endif #ifndef HAVE_WSTRING // Some C++ libraries (gcc 2.95) don't define this. typedef basic_string wstring; #endif #ifndef HAVE_STREAMSIZE // Some C++ libraries (Irix) don't define this. typedef long streamsize; #endif #ifndef HAVE_IOS_TYPEDEFS typedef int ios_openmode; typedef int ios_fmtflags; typedef int ios_iostate; // Old iostream libraries used ios::seek_dir instead of ios::seekdir. typedef ios::seek_dir ios_seekdir; #else typedef ios::openmode ios_openmode; typedef ios::fmtflags ios_fmtflags; typedef ios::iostate ios_iostate; typedef ios::seekdir ios_seekdir; #endif // Apple has an outdated libstdc++. Not all is lost, though, as we can fill // in some important missing functions. #if defined(__GLIBCXX__) && __GLIBCXX__ <= 20070719 typedef decltype(nullptr) nullptr_t; template struct remove_reference {typedef T type;}; template struct remove_reference {typedef T type;}; template struct remove_reference{typedef T type;}; template typename remove_reference::type &&move(T &&t) { return static_cast::type&&>(t); } #endif #ifdef _MSC_VER #define ALWAYS_INLINE __forceinline #elif defined(__GNUC__) #define ALWAYS_INLINE __attribute__((always_inline)) inline #else #define ALWAYS_INLINE inline #endif #ifdef FORCE_INLINING // If FORCE_INLINING is defined, we use the keyword __forceinline, which tells // MS VC++ to override its internal benefit heuristic and inline the fn if it // is technically possible to do so. #define INLINE ALWAYS_INLINE #else #define INLINE inline #endif // Determine the availability of C++11 features. #if defined(__has_extension) // Clang magic. # if __has_extension(cxx_constexpr) # if !defined(__apple_build_version__) || __apple_build_version__ >= 5000000 # define CONSTEXPR constexpr # endif # endif # if __has_extension(cxx_noexcept) # define NOEXCEPT noexcept # endif # if __has_extension(cxx_rvalue_references) && (__cplusplus >= 201103L) # define USE_MOVE_SEMANTICS # define MOVE(x) move(x) # endif # if __has_extension(cxx_override_control) && (__cplusplus >= 201103L) # define FINAL final # endif # if __has_extension(cxx_defaulted_functions) # define DEFAULT_CTOR = default # define DEFAULT_DTOR = default # define DEFAULT_ASSIGN = default # endif # if __has_extension(cxx_deleted_functions) # define DELETED = delete # endif #elif defined(__GNUC__) // GCC // Starting at GCC 4.4 # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) # define DEFAULT_CTOR = default # define DEFAULT_DTOR = default # define DEFAULT_ASSIGN = default # define DELETED = delete # endif // Starting at GCC 4.6 # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # define CONSTEXPR constexpr # define NOEXCEPT noexcept # define USE_MOVE_SEMANTICS # define MOVE(x) move(x) # endif // Starting at GCC 4.7 # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) # define FINAL final # endif // GCC defines several macros which we can query. List of all supported // builtin macros: https://gcc.gnu.org/projects/cxx-status.html # if !defined(CONSTEXPR) && __cpp_constexpr >= 200704 # define CONSTEXPR constexpr # endif #elif defined(_MSC_VER) && _MSC_VER >= 1900 // Visual Studio 2015 # define CONSTEXPR constexpr # define NOEXCEPT noexcept # define USE_MOVE_SEMANTICS # define FINAL final # define MOVE(x) move(x) #elif defined(_MSC_VER) && _MSC_VER >= 1600 // Visual Studio 2010 # define NOEXCEPT throw() # define USE_MOVE_SEMANTICS # define FINAL sealed # define MOVE(x) move(x) #endif #if defined(_MSC_VER) && _MSC_VER >= 1800 // Visual Studio 2013 # define DEFAULT_CTOR = default # define DEFAULT_DTOR = default # define DEFAULT_ASSIGN = default # define DELETED = delete #endif // Fallbacks if features are not supported #ifndef CONSTEXPR # define CONSTEXPR INLINE # define ALWAYS_INLINE_CONSTEXPR ALWAYS_INLINE #else # define ALWAYS_INLINE_CONSTEXPR ALWAYS_INLINE CONSTEXPR #endif #ifndef NOEXCEPT # define NOEXCEPT #endif #ifndef MOVE # define MOVE(x) x #endif #ifndef FINAL # define FINAL #endif #ifndef DEFAULT_CTOR # define DEFAULT_CTOR {} #endif #ifndef DEFAULT_DTOR # define DEFAULT_DTOR {} #endif #ifndef DEFAULT_ASSIGN # define DEFAULT_ASSIGN {return *this;} #endif #ifndef DELETED # define DELETED {assert(false);} # define DELETED_ASSIGN {assert(false);return *this;} #else # define DELETED_ASSIGN DELETED #endif #if !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES) // This macro must be used to export an instantiated template class from a // DLL. If the template class name itself contains commas, it may be // necessary to first define a macro for the class name, to allow proper macro // parameter passing. #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname) \ exptp template class expcl classname; #else #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname) #endif // We define the macro PUBLISHED to mark C++ methods that are to be published // via interrogate to scripting languages. However, if we're not running the // interrogate pass (CPPPARSER isn't defined), this maps to public. #define PUBLISHED public #endif // CPPPARSER // The ReferenceCount class is defined later, within Panda, but we need to // pass around forward references to it here at the very low level. class ReferenceCount; // We need a pointer to a global MemoryHook object, to manage all malloc and // free requests from Panda. See the comments in MemoryHook itself. class MemoryHook; EXPCL_DTOOL extern MemoryHook *memory_hook; EXPCL_DTOOL void init_memory_hook(); // Now redefine some handy macros to hook into the above MemoryHook object. #ifndef USE_MEMORY_NOWRAPPERS #define PANDA_MALLOC_SINGLE(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_single(size), MEMORY_HOOK_ALIGNMENT)) #define PANDA_FREE_SINGLE(ptr) memory_hook->heap_free_single(ptr) #define PANDA_MALLOC_ARRAY(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_array(size), MEMORY_HOOK_ALIGNMENT)) #define PANDA_REALLOC_ARRAY(ptr, size) (ASSUME_ALIGNED(memory_hook->heap_realloc_array(ptr, size), MEMORY_HOOK_ALIGNMENT)) #define PANDA_FREE_ARRAY(ptr) memory_hook->heap_free_array(ptr) #else #define PANDA_MALLOC_SINGLE(size) ::malloc(size) #define PANDA_FREE_SINGLE(ptr) ::free(ptr) #define PANDA_MALLOC_ARRAY(size) ::malloc(size) #define PANDA_REALLOC_ARRAY(ptr, size) ::realloc(ptr, size) #define PANDA_FREE_ARRAY(ptr) ::free(ptr) #endif // USE_MEMORY_NOWRAPPERS #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS) // We need another forward-reference function to allow low-level code to // cooperatively yield the timeslice, in SIMPLE_THREADS mode. extern EXPCL_DTOOL void (*global_thread_yield)(); extern EXPCL_DTOOL void (*global_thread_consider_yield)(); INLINE void thread_yield() { (*global_thread_yield)(); } INLINE void thread_consider_yield() { (*global_thread_consider_yield)(); } #else INLINE void thread_yield() { } INLINE void thread_consider_yield() { } #endif // HAVE_THREADS && SIMPLE_THREADS #if defined(USE_TAU) && defined(WIN32) // Hack around tau's lack of DLL export declarations for Profiler class. extern EXPCL_DTOOL bool __tau_shutdown; class EXPCL_DTOOL TauProfile { public: TauProfile(void *&tautimer, char *name, char *type, int group, char *group_name) { Tau_profile_c_timer(&tautimer, name, type, group, group_name); _tautimer = tautimer; TAU_PROFILE_START(_tautimer); } ~TauProfile() { if (!__tau_shutdown) { TAU_PROFILE_STOP(_tautimer); } } private: void *_tautimer; }; #undef TAU_PROFILE #define TAU_PROFILE(name, type, group) \ static void *__tautimer; \ TauProfile __taupr(__tautimer, name, type, group, #group) #undef TAU_PROFILE_EXIT #define TAU_PROFILE_EXIT(msg) \ __tau_shutdown = true; \ Tau_exit(msg); #endif // USE_TAU #endif // __cplusplus #endif