Panda3D
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.
144 typedef 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_PTMALLOC2)
391 // But not this one. For some reason it crashes when we try to build it with
392 // alignment 16. So if we're using ptmalloc2, we need to enforce alignment
393 // externally.
394 #define MEMORY_HOOK_DO_ALIGN 1
395 
396 #elif (defined(IS_OSX) || defined(_WIN64)) && !defined(__AVX__)
397 // The OS-provided malloc implementation will do the required alignment.
398 #undef MEMORY_HOOK_DO_ALIGN
399 
400 #elif defined(MEMORY_HOOK_DO_ALIGN)
401 // We need memory alignment, and we're willing to provide it ourselves.
402 
403 #else
404 // We need memory alignment, and we haven't specified whether it should be
405 // provided on top of the existing malloc library, or otherwise. Let's rely
406 // on dlmalloc to provide it, it seems to be the most memory-efficient option.
407 #define USE_MEMORY_DLMALLOC 1
408 
409 #endif
410 
411 #ifdef LINMATH_ALIGN
412 /* We require 16-byte alignment of certain structures, to support SSE2. We
413  don't strictly have to align everything, but it's just easier to do so. */
414 #if defined(HAVE_EIGEN) && defined(__AVX__) && defined(STDFLOAT_DOUBLE)
415 /* Eigen uses AVX instructions, but let's only enable this when compiling with
416  double precision, so that we can keep our ABI a bit more stable. */
417 #define MEMORY_HOOK_ALIGNMENT 32
418 #else
419 #define MEMORY_HOOK_ALIGNMENT 16
420 #endif
421 /* Otherwise, align to two words. This seems to be pretty standard to the
422  point where some code may rely on this being the case. */
423 #elif defined(IS_OSX) || NATIVE_WORDSIZE >= 64
424 #define MEMORY_HOOK_ALIGNMENT 16
425 #else
426 #define MEMORY_HOOK_ALIGNMENT 8
427 #endif
428 
429 #ifdef HAVE_EIGEN
430 /* Make sure that Eigen doesn't assume alignment guarantees we don't offer. */
431 #define EIGEN_MAX_ALIGN_BYTES MEMORY_HOOK_ALIGNMENT
432 #ifndef EIGEN_MPL2_ONLY
433 #define EIGEN_MPL2_ONLY 1
434 #endif
435 #if !defined(_DEBUG) && !defined(EIGEN_NO_DEBUG)
436 #define EIGEN_NO_DEBUG 1
437 #endif
438 #endif
439 
440 /* Determine our memory-allocation requirements. */
441 #if defined(USE_MEMORY_PTMALLOC2) || defined(USE_MEMORY_DLMALLOC) || defined(DO_MEMORY_USAGE) || defined(MEMORY_HOOK_DO_ALIGN)
442 /* In this case we have some custom memory management requirements. */
443 #else
444 /* Otherwise, if we have no custom memory management needs at all, we
445  might as well turn it all off and go straight to the OS-level
446  calls. */
447 #define USE_MEMORY_NOWRAPPERS 1
448 #endif
449 
450 /* We must always use the STL allocator nowadays, because we have
451  redefined the constructors for pvector, pmap, etc. */
452 #define USE_STL_ALLOCATOR 1
453 
454 /*
455  We define the macros BEGIN_PUBLISH and END_PUBLISH to bracket
456  functions and global variable definitions that are to be published
457  via interrogate to scripting languages. Also, the macro BLOCKING is
458  used to flag any function or method that might perform I/O blocking
459  and thus needs to release Python threads for its duration.
460  */
461 #ifdef CPPPARSER
462 #define BEGIN_PUBLISH __begin_publish
463 #define END_PUBLISH __end_publish
464 #define BLOCKING __blocking
465 #define MAKE_PROPERTY(property_name, ...) __make_property(property_name, __VA_ARGS__)
466 #define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__)
467 #define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
468 #define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
469 #define MAKE_MAP_PROPERTY(property_name, ...) __make_map_property(property_name, __VA_ARGS__)
470 #define MAKE_MAP_KEYS_SEQ(property_name, ...) __make_map_keys_seq(property_name, __VA_ARGS__)
471 #define EXTENSION(x) __extension x
472 #define EXTEND __extension
473 #else
474 #define BEGIN_PUBLISH
475 #define END_PUBLISH
476 #define BLOCKING
477 #define MAKE_PROPERTY(property_name, ...)
478 #define MAKE_PROPERTY2(property_name, ...)
479 #define MAKE_SEQ(seq_name, num_name, element_name)
480 #define MAKE_SEQ_PROPERTY(property_name, ...)
481 #define MAKE_MAP_PROPERTY(property_name, ...)
482 #define MAKE_MAP_KEYS_SEQ(property_name, ...)
483 #define EXTENSION(x)
484 #define EXTEND
485 #endif
486 
487 /* These symbols are used in dtoolsymbols.h and pandasymbols.h. */
488 #if defined(WIN32_VC) && !defined(CPPPARSER) && !defined(LINK_ALL_STATIC)
489 #define EXPORT_CLASS __declspec(dllexport)
490 #define IMPORT_CLASS __declspec(dllimport)
491 #elif __GNUC__ >= 4 && !defined(CPPPARSER) && !defined(LINK_ALL_STATIC)
492 #define EXPORT_CLASS __attribute__((visibility("default")))
493 #define IMPORT_CLASS
494 #else
495 #define EXPORT_CLASS
496 #define IMPORT_CLASS
497 #endif
498 
499 /* "extern template" is now part of the C++11 standard. */
500 #if defined(CPPPARSER) || defined(LINK_ALL_STATIC)
501 #define EXPORT_TEMPL
502 #define IMPORT_TEMPL
503 #elif defined(_MSC_VER)
504 /* Nowadays, we'd define both of these as "extern" in all cases, so that
505  the header file always marks the symbol as "extern" and the .cxx file
506  explicitly instantiates it. However, MSVC versions before 2013 break
507  the spec by explicitly disallowing it, so we have to instantiate the
508  class from the header file. Fortunately, its linker is okay with the
509  duplicate template instantiations that this causes. */
510 #define EXPORT_TEMPL
511 #define IMPORT_TEMPL extern
512 #else
513 #define EXPORT_TEMPL extern
514 #define IMPORT_TEMPL extern
515 #endif
516 
517 #ifdef __cplusplus
518 #include "dtoolbase_cc.h"
519 #endif
520 
521 #endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.