Panda3D
Loading...
Searching...
No Matches
dtoolbase.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 dtoolbase.h
10 * @author drose
11 * @date 2000-09-12
12 */
13
14/* This file is included at the beginning of every header file and/or
15 C or C++ file. It must be compilable for C as well as C++ files,
16 so no C++-specific code or syntax can be put here. See
17 dtoolbase_cc.h for C++-specific stuff. */
18
19#ifndef DTOOLBASE_H
20#define DTOOLBASE_H
21
22#include "dtool_config.h"
23
24/* Make sure WIN32 and WIN32_VC are defined when using MSVC */
25#if defined(_WIN32) || defined(_WIN64)
26#ifndef WIN32
27#define WIN32
28#endif
29#ifdef _MSC_VER
30#ifndef WIN32_VC
31#define WIN32_VC
32#endif
33#endif
34#endif
35
36#ifdef WIN32_VC
37/* These warning pragmas must appear before anything else for VC++ to
38 respect them. Sheesh. */
39
40/* C4231: extern before template instantiation */
41/* For some reason, this particular warning won't disable. */
42#pragma warning (disable : 4231)
43/* C4786: 255 char debug symbols */
44#pragma warning (disable : 4786)
45/* C4251: needs dll interface */
46#pragma warning (disable : 4251)
47/* C4503: decorated name length exceeded */
48#pragma warning (disable : 4503)
49/* C4305: truncation from 'const double' to 'float' */
50#pragma warning (disable : 4305)
51/* C4250: 'myclass' : inherits 'baseclass::member' via dominance */
52#pragma warning (disable : 4250)
53/* C4355: 'this' : used in base member initializer list */
54#pragma warning (disable : 4355)
55/* C4244: 'initializing' : conversion from 'double' to 'float', possible loss of data */
56#pragma warning (disable : 4244)
57/* C4267: 'var' : conversion from 'size_t' to 'type', possible loss of data */
58#pragma warning (disable : 4267)
59/* C4577: 'noexcept' used with no exception handling mode specified */
60#pragma warning (disable : 4577)
61#endif /* WIN32_VC */
62
63/* Windows likes to define min() and max() macros, which will conflict with
64 std::min() and std::max() respectively, unless we do this: */
65#ifdef WIN32
66#ifndef NOMINMAX
67#define NOMINMAX
68#endif
69#endif
70
71#ifndef __has_builtin
72#define __has_builtin(x) 0
73#endif
74
75#ifndef __has_attribute
76#define __has_attribute(x) 0
77#endif
78
79// Use NODEFAULT to optimize a switch() stmt to tell MSVC to automatically go
80// to the final untested case after it has failed all the other cases (i.e.
81// 'assume at least one of the cases is always true')
82#ifdef _DEBUG
83#define NODEFAULT default: assert(0); break;
84#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) || __has_builtin(__builtin_unreachable)
85#define NODEFAULT default: __builtin_unreachable();
86#elif defined(_MSC_VER)
87#define NODEFAULT default: __assume(0); // special VC keyword
88#else
89#define NODEFAULT
90#endif
91
92// Use this to hint the compiler that a memory address is aligned.
93#if __has_builtin(__builtin_assume_aligned) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
94#define ASSUME_ALIGNED(x, y) (__builtin_assume_aligned(x, y))
95#else
96#define ASSUME_ALIGNED(x, y) (x)
97#endif
98
99#if __has_attribute(assume_aligned) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
100#define RETURNS_ALIGNED(x) __attribute__((assume_aligned(x)))
101#else
102#define RETURNS_ALIGNED(x)
103#endif
104
105#ifdef __GNUC__
106#define LIKELY(x) __builtin_expect(!!(x), 1)
107#define UNLIKELY(x) __builtin_expect(!!(x), 0)
108#else
109#define LIKELY(x) (x)
110#define UNLIKELY(x) (x)
111#endif
112
113/*
114 include win32 defns for everything up to WinServer2003, and assume
115 I'm smart enough to use GetProcAddress for backward compat on
116 w95/w98 for newer fns
117*/
118#ifdef _WIN32_WINNT
119#undef _WIN32_WINNT
120#endif
121#define _WIN32_WINNT 0x0502
122
123#ifdef __cplusplus
124#ifndef __STDC_LIMIT_MACROS
125#define __STDC_LIMIT_MACROS
126#endif
127#ifndef __STDC_CONSTANT_MACROS
128#define __STDC_CONSTANT_MACROS
129#endif
130#endif
131
132// This is a workaround for a glibc bug that is triggered by clang when
133// compiling with -ffast-math.
134#if defined(__clang__) && defined(__GLIBC__)
135#include <sys/cdefs.h>
136#ifndef __extern_always_inline
137#define __extern_always_inline extern __always_inline
138#endif
139#endif
140
141// Instead of including the Python headers, which will implicitly add a linker
142// flag to link in Python, we'll just excerpt the forward declaration of
143// PyObject.
144typedef struct _object PyObject;
145
146#ifndef HAVE_EIGEN
147// If we don't have the Eigen library, don't define LINMATH_ALIGN.
148#undef LINMATH_ALIGN
149#endif
150
151#include "dtoolsymbols.h"
152
153// always include assert.h until drose unbreaks it for opt4
154#include <assert.h>
155
156#ifdef __GNUC__
157// Large file >2GB support this needs be be before systypes.h and other C
158// headers
159#define _FILE_OFFSET_BITS 64
160#define _LARGEFILE_SOURCE 1
161#endif
162
163#ifdef PHAVE_TYPES_H
164#include <types.h>
165#endif
166
167#ifdef PHAVE_SYS_TYPES_H
168#include <sys/types.h>
169#endif
170
171#ifdef PHAVE_MALLOC_H
172#include <malloc.h>
173#endif
174
175#ifdef PHAVE_SYS_MALLOC_H
176#include <sys/malloc.h>
177#endif
178
179#ifdef PHAVE_ALLOCA_H
180#include <alloca.h>
181#endif
182
183#ifdef PHAVE_UNISTD_H
184#include <unistd.h>
185#endif
186
187#ifdef PHAVE_IO_H
188#include <io.h>
189#endif
190
191#ifdef PHAVE_LOCALE_H
192#include <locale.h>
193#endif
194
195#ifdef PHAVE_STRING_H
196#include <string.h>
197#endif
198
199#ifdef PHAVE_STDLIB_H
200#include <stdlib.h>
201#endif
202
203#ifdef PHAVE_LIMITS_H
204#include <limits.h>
205#endif
206
207#ifdef PHAVE_SYS_TIME_H
208#include <sys/time.h>
209#endif
210
211#ifdef PHAVE_STDINT_H
212#include <stdint.h>
213#endif
214
215#ifdef CPPPARSER
216#include <stdtypedefs.h>
217
218// Also pick up the forward declaration of PyObject.
219#include <Python.h>
220#endif
221
222#ifdef USE_TAU
223/* If we're building with the Tau instrumentor, include the
224 appropriate header file to pick up the TAU macros. */
225#include <TAU.h>
226#include <Profile/Profiler.h>
227#else
228/* Otherwise, if we're not building with the Tau instrumentor, turn
229 off all the TAU macros. We could include the Tau header file to do
230 this, but it's better not to assume that Tau is installed. */
231#define TAU_TYPE_STRING(profileString, str)
232#define TAU_PROFILE(name, type, group)
233#define TAU_PROFILE_TIMER(var, name, type, group)
234#define TAU_PROFILE_START(var)
235#define TAU_PROFILE_STOP(var)
236#define TAU_PROFILE_STMT(stmt)
237#define TAU_PROFILE_EXIT(msg)
238#define TAU_PROFILE_INIT(argc, argv)
239#define TAU_PROFILE_SET_NODE(node)
240#define TAU_PROFILE_SET_CONTEXT(context)
241#define TAU_PROFILE_SET_GROUP_NAME(newname)
242#define TAU_PROFILE_TIMER_SET_GROUP_NAME(t, newname)
243#define TAU_PROFILE_CALLSTACK()
244#define TAU_DB_DUMP()
245#define TAU_DB_PURGE()
246
247#define TAU_REGISTER_CONTEXT_EVENT(event, name)
248#define TAU_CONTEXT_EVENT(event, data)
249#define TAU_DISABLE_CONTEXT_EVENT(event)
250#define TAU_ENABLE_CONTEXT_EVENT(event)
251
252#define TAU_REGISTER_EVENT(event, name)
253#define TAU_EVENT(event, data)
254#define TAU_EVENT_DISABLE_MIN(event)
255#define TAU_EVENT_DISABLE_MAX(event)
256#define TAU_EVENT_DISABLE_MEAN(event)
257#define TAU_EVENT_DISABLE_STDDEV(event)
258#define TAU_REPORT_STATISTICS()
259#define TAU_REPORT_THREAD_STATISTICS()
260#define TAU_REGISTER_THREAD()
261#define TAU_REGISTER_FORK(id, op)
262#define TAU_ENABLE_INSTRUMENTATION()
263#define TAU_DISABLE_INSTRUMENTATION()
264#define TAU_ENABLE_GROUP(group)
265#define TAU_DISABLE_GROUP(group)
266#define TAU_ENABLE_GROUP_NAME(group)
267#define TAU_DISABLE_GROUP_NAME(group)
268#define TAU_ENABLE_ALL_GROUPS()
269#define TAU_DISABLE_ALL_GROUPS()
270#define TAU_TRACK_MEMORY()
271#define TAU_TRACK_MEMORY_HERE()
272#define TAU_ENABLE_TRACKING_MEMORY()
273#define TAU_DISABLE_TRACKING_MEMORY()
274#define TAU_ENABLE_TRACKING_MUSE_EVENTS()
275#define TAU_DISABLE_TRACKING_MUSE_EVENTS()
276#define TAU_TRACK_MUSE_EVENTS()
277#define TAU_SET_INTERRUPT_INTERVAL(value)
278
279#define TAU_TRACE_SENDMSG(type, destination, length)
280#define TAU_TRACE_RECVMSG(type, source, length)
281
282#define TAU_MAPPING(stmt, group) stmt
283#define TAU_MAPPING_OBJECT(FuncInfoVar)
284#define TAU_MAPPING_LINK(FuncInfoVar, Group)
285#define TAU_MAPPING_PROFILE(FuncInfoVar)
286#define TAU_MAPPING_CREATE(name, type, key, groupname, tid)
287#define TAU_MAPPING_PROFILE_TIMER(Timer, FuncInfoVar, tid)
288#define TAU_MAPPING_TIMER_CREATE(t, name, type, gr, group_name)
289#define TAU_MAPPING_PROFILE_START(Timer, tid)
290#define TAU_MAPPING_PROFILE_STOP(tid)
291#define TAU_MAPPING_PROFILE_EXIT(msg, tid)
292#define TAU_MAPPING_DB_DUMP(tid)
293#define TAU_MAPPING_DB_PURGE(tid)
294#define TAU_MAPPING_PROFILE_SET_NODE(node, tid)
295#define TAU_MAPPING_PROFILE_SET_GROUP_NAME(timer, name)
296#define TAU_PROFILE_TIMER_SET_NAME(t, newname)
297#define TAU_PROFILE_TIMER_SET_TYPE(t, newname)
298#define TAU_PROFILE_TIMER_SET_GROUP(t, id)
299#define TAU_MAPPING_PROFILE_SET_NAME(timer, name)
300#define TAU_MAPPING_PROFILE_SET_TYPE(timer, name)
301#define TAU_MAPPING_PROFILE_SET_GROUP(timer, id)
302#define TAU_MAPPING_PROFILE_GET_GROUP_NAME(timer)
303#define TAU_MAPPING_PROFILE_GET_GROUP(timer)
304#define TAU_MAPPING_PROFILE_GET_NAME(timer)
305#define TAU_MAPPING_PROFILE_GET_TYPE(timer)
306
307#define TAU_PHASE(name, type, group)
308#define TAU_PHASE_CREATE_STATIC(var, name, type, group)
309#define TAU_PHASE_CREATE_DYNAMIC(var, name, type, group)
310#define TAU_PHASE_START(var)
311#define TAU_PHASE_STOP(var)
312#define TAU_GLOBAL_PHASE(timer, name, type, group)
313#define TAU_GLOBAL_PHASE_START(timer)
314#define TAU_GLOBAL_PHASE_STOP(timer)
315#define TAU_GLOBAL_PHASE_EXTERNAL(timer)
316#define TAU_GLOBAL_TIMER(timer, name, type, group)
317#define TAU_GLOBAL_TIMER_EXTERNAL(timer)
318#define TAU_GLOBAL_TIMER_START(timer)
319#define TAU_GLOBAL_TIMER_STOP()
320
321#endif /* USE_TAU */
322
323/* Try to infer the endianness of the host based on compiler
324 predefined macros. For systems on which the compiler does not
325 define these macros, we rely on ppremake to define WORDS_BIGENDIAN
326 correctly. For systems on which the compiler *does* define these
327 macros, we ignore what ppremake said and define WORDS_BIGENDIAN
328 correctly here. (This is essential on OSX, which requires
329 compiling each file twice in different modes, for universal binary
330 support.) */
331
332#if defined(__LITTLE_ENDIAN__) || defined(__i386__)
333#undef WORDS_BIGENDIAN
334
335#elif defined(__BIG_ENDIAN__) || defined(__ppc__)
336#undef WORDS_BIGENDIAN
337#define WORDS_BIGENDIAN 1
338
339#endif
340
341/* Try to determine if we're compiling in a 64-bit mode. */
342
343#ifdef __WORDSIZE
344#define NATIVE_WORDSIZE __WORDSIZE
345#elif defined(_LP64) || defined(_WIN64)
346#define NATIVE_WORDSIZE 64
347#else
348#define NATIVE_WORDSIZE 32
349#endif
350
351/* Some byte-alignment macros. */
352#ifdef CPPPARSER
353#define ALIGN_4BYTE
354#define ALIGN_8BYTE
355#define ALIGN_16BYTE
356#define ALIGN_32BYTE
357#define ALIGN_64BYTE
358#elif defined(_MSC_VER)
359#define ALIGN_4BYTE __declspec(align(4))
360#define ALIGN_8BYTE __declspec(align(8))
361#define ALIGN_16BYTE __declspec(align(16))
362#define ALIGN_32BYTE __declspec(align(32))
363#define ALIGN_64BYTE __declspec(align(64))
364#elif defined(__GNUC__)
365#define ALIGN_4BYTE __attribute__ ((aligned (4)))
366#define ALIGN_8BYTE __attribute__ ((aligned (8)))
367#define ALIGN_16BYTE __attribute__ ((aligned (16)))
368#define ALIGN_32BYTE __attribute__ ((aligned (32)))
369#define ALIGN_64BYTE __attribute__ ((aligned (64)))
370#else
371#define ALIGN_4BYTE
372#define ALIGN_8BYTE
373#define ALIGN_16BYTE
374#define ALIGN_32BYTE
375#define ALIGN_64BYTE
376#endif
377
378// Do we need to implement memory-alignment enforcement within the MemoryHook
379// class, or will the underlying malloc implementation provide it
380// automatically?
381#if !defined(LINMATH_ALIGN)
382// We don't actually require any special memory-alignment beyond what the
383// underlying implementation is likely to provide anyway.
384#undef MEMORY_HOOK_DO_ALIGN
385
386#elif defined(USE_MEMORY_DLMALLOC)
387// This specialized malloc implementation can perform the required alignment.
388#undef MEMORY_HOOK_DO_ALIGN
389
390#elif defined(USE_MEMORY_MIMALLOC)
391// This one does, too.
392#undef MEMORY_HOOK_DO_ALIGN
393
394#elif defined(USE_MEMORY_PTMALLOC2)
395// But not this one. For some reason it crashes when we try to build it with
396// alignment 16. So if we're using ptmalloc2, we need to enforce alignment
397// externally.
398#define MEMORY_HOOK_DO_ALIGN 1
399
400#elif (defined(IS_OSX) || defined(_WIN64)) && !defined(__AVX__)
401// The OS-provided malloc implementation will do the required alignment.
402#undef MEMORY_HOOK_DO_ALIGN
403
404#elif defined(MEMORY_HOOK_DO_ALIGN)
405// We need memory alignment, and we're willing to provide it ourselves.
406
407#else
408// We need memory alignment, and we haven't specified whether it should be
409// provided on top of the existing malloc library, or otherwise. Let's rely
410// on dlmalloc to provide it, it seems to be the most memory-efficient option.
411#define USE_MEMORY_DLMALLOC 1
412
413#endif
414
415#ifdef LINMATH_ALIGN
416/* We require 16-byte alignment of certain structures, to support SSE2. We
417 don't strictly have to align everything, but it's just easier to do so. */
418#if defined(HAVE_EIGEN) && defined(__AVX__) && defined(STDFLOAT_DOUBLE)
419/* Eigen uses AVX instructions, but let's only enable this when compiling with
420 double precision, so that we can keep our ABI a bit more stable. */
421#define MEMORY_HOOK_ALIGNMENT 32
422#else
423#define MEMORY_HOOK_ALIGNMENT 16
424#endif
425/* Otherwise, align to two words. This seems to be pretty standard to the
426 point where some code may rely on this being the case. */
427#elif defined(IS_OSX) || NATIVE_WORDSIZE >= 64
428#define MEMORY_HOOK_ALIGNMENT 16
429#else
430#define MEMORY_HOOK_ALIGNMENT 8
431#endif
432
433#ifdef HAVE_EIGEN
434/* Make sure that Eigen doesn't assume alignment guarantees we don't offer. */
435#define EIGEN_MAX_ALIGN_BYTES MEMORY_HOOK_ALIGNMENT
436#ifndef EIGEN_MPL2_ONLY
437#define EIGEN_MPL2_ONLY 1
438#endif
439#if !defined(_DEBUG) && !defined(EIGEN_NO_DEBUG)
440#define EIGEN_NO_DEBUG 1
441#endif
442#endif
443
444/* Determine our memory-allocation requirements. */
445#if defined(USE_MEMORY_MIMALLOC) || defined(USE_MEMORY_PTMALLOC2) || defined(USE_MEMORY_DLMALLOC) || defined(DO_MEMORY_USAGE) || defined(MEMORY_HOOK_DO_ALIGN)
446/* In this case we have some custom memory management requirements. */
447#else
448/* Otherwise, if we have no custom memory management needs at all, we
449 might as well turn it all off and go straight to the OS-level
450 calls. */
451#define USE_MEMORY_NOWRAPPERS 1
452#endif
453
454/* We must always use the STL allocator nowadays, because we have
455 redefined the constructors for pvector, pmap, etc. */
456#define USE_STL_ALLOCATOR 1
457
458/*
459 We define the macros BEGIN_PUBLISH and END_PUBLISH to bracket
460 functions and global variable definitions that are to be published
461 via interrogate to scripting languages. Also, the macro BLOCKING is
462 used to flag any function or method that might perform I/O blocking
463 and thus needs to release Python threads for its duration.
464 */
465#ifdef CPPPARSER
466#define BEGIN_PUBLISH __begin_publish
467#define END_PUBLISH __end_publish
468#define BLOCKING __blocking
469#define MAKE_PROPERTY(property_name, ...) __make_property(property_name, __VA_ARGS__)
470#define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__)
471#define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
472#define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
473#define MAKE_MAP_PROPERTY(property_name, ...) __make_map_property(property_name, __VA_ARGS__)
474#define MAKE_MAP_KEYS_SEQ(property_name, ...) __make_map_keys_seq(property_name, __VA_ARGS__)
475#define EXTENSION(x) __extension x
476#define EXTEND __extension
477#else
478#define BEGIN_PUBLISH
479#define END_PUBLISH
480#define BLOCKING
481#define MAKE_PROPERTY(property_name, ...)
482#define MAKE_PROPERTY2(property_name, ...)
483#define MAKE_SEQ(seq_name, num_name, element_name)
484#define MAKE_SEQ_PROPERTY(property_name, ...)
485#define MAKE_MAP_PROPERTY(property_name, ...)
486#define MAKE_MAP_KEYS_SEQ(property_name, ...)
487#define EXTENSION(x)
488#define EXTEND
489#endif
490
491/* These symbols are used in dtoolsymbols.h and pandasymbols.h. */
492#if defined(WIN32_VC) && !defined(CPPPARSER) && !defined(LINK_ALL_STATIC)
493#define EXPORT_CLASS __declspec(dllexport)
494#define IMPORT_CLASS __declspec(dllimport)
495#elif __GNUC__ >= 4 && !defined(CPPPARSER) && !defined(LINK_ALL_STATIC)
496#define EXPORT_CLASS __attribute__((visibility("default")))
497#define IMPORT_CLASS
498#else
499#define EXPORT_CLASS
500#define IMPORT_CLASS
501#endif
502
503/* "extern template" is now part of the C++11 standard. */
504#if defined(CPPPARSER) || defined(LINK_ALL_STATIC)
505#define EXPORT_TEMPL
506#define IMPORT_TEMPL
507#elif defined(_MSC_VER)
508/* Nowadays, we'd define both of these as "extern" in all cases, so that
509 the header file always marks the symbol as "extern" and the .cxx file
510 explicitly instantiates it. However, MSVC versions before 2013 break
511 the spec by explicitly disallowing it, so we have to instantiate the
512 class from the header file. Fortunately, its linker is okay with the
513 duplicate template instantiations that this causes. */
514#define EXPORT_TEMPL
515#define IMPORT_TEMPL extern
516#else
517#define EXPORT_TEMPL extern
518#define IMPORT_TEMPL extern
519#endif
520
521#ifdef __cplusplus
522#include "dtoolbase_cc.h"
523#endif
524
525#endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.