Panda3D
pandaSystem.cxx
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 pandaSystem.cxx
10 * @author drose
11 * @date 2005-01-26
12 */
13
14#include "pandaSystem.h"
15#include "pandaVersion.h"
16#include "dtool_platform.h"
17
18using std::string;
19
20PandaSystem *PandaSystem::_global_ptr = nullptr;
21TypeHandle PandaSystem::_type_handle;
22
23/**
24 * Don't try to construct a PandaSystem object; there is only one of these,
25 * and it constructs itself. Use get_global_ptr() to get a pointer to the one
26 * PandaSystem.
27 */
28PandaSystem::
29PandaSystem() :
30 _systems(get_class_type())
31{
32 _system_names_dirty = false;
33
34 // These are settable via Config.prc, but only in development (!NDEBUG)
35 // mode, and only if they are not already defined.
36 _package_version_string = PANDA_PACKAGE_VERSION_STR;
37 _package_host_url = PANDA_PACKAGE_HOST_URL;
38
39#ifdef STDFLOAT_DOUBLE
40 add_system("stdfloat-double");
41#endif
42
43#ifdef HAVE_EIGEN
44 add_system("eigen");
45#ifdef LINMATH_ALIGN
46 set_system_tag("eigen", "vectorize", "1");
47#else
48 set_system_tag("eigen", "vectorize", "0");
49#endif
50#ifdef __AVX__
51 set_system_tag("eigen", "avx", "1");
52#else
53 set_system_tag("eigen", "avx", "0");
54#endif
55#endif // HAVE_EIGEN
56
57#ifdef USE_MEMORY_DLMALLOC
58 set_system_tag("system", "malloc", "dlmalloc");
59#elif defined(USE_MEMORY_PTMALLOC2)
60 set_system_tag("system", "malloc", "ptmalloc2");
61#else
62 set_system_tag("system", "malloc", "malloc");
63#endif
64
65#ifdef _LIBCPP_VERSION
66 set_system_tag("system", "stdlib", "libc++");
67#elif defined(__GLIBCXX__)
68 set_system_tag("system", "stdlib", "libstdc++");
69#endif
70}
71
72/**
73 * Don't try to destruct the global PandaSystem object.
74 */
75PandaSystem::
76~PandaSystem() {
77}
78
79/**
80 * Returns the current version of Panda, expressed as a string, e.g. "1.0.0".
81 * The string will end in the letter "c" if this build does not represent an
82 * official version.
83 */
84string PandaSystem::
86 return PANDA_VERSION_STR;
87}
88
89/**
90 * Returns the version of the Panda3D distributable package that provides this
91 * build of Panda.
92 *
93 * When the currently-executing version of Panda was loaded from a
94 * distributable package, such as via the browser plugin, then this string
95 * will be nonempty and will contain the corresponding version string. You
96 * can build applications that use this particular version of Panda by
97 * requesting it in the pdef file, using "panda3d", this version string, and
98 * the download host provided by get_package_host_url().
99 *
100 * If this string is empty, then the currently-executing Panda was built
101 * independently, and is not part of a distributable package.
102 *
103 * This string is set explicitly at compilation time. Normally, it should be
104 * set to a nonempty string only when building a Panda3D package for
105 * distribution.
106 */
109#ifdef NDEBUG
110 return PANDA_PACKAGE_VERSION_STR;
111#else
112 return get_global_ptr()->_package_version_string;
113#endif
114}
115
116/**
117 * Returns the URL of the download server that provides the Panda3D
118 * distributable package currently running. This can be used, along with the
119 * get_package_version_string(), to uniquely identify the running version of
120 * Panda among distributable Panda versions.
121 *
122 * See get_package_version_string() for more information.
123 *
124 * This string is set explicitly at compilation time. Normally, it should be
125 * set to a nonempty string only when building a Panda3D package for
126 * distribution.
127 */
130#ifdef NDEBUG
131 return PANDA_PACKAGE_HOST_URL;
132#else
133 return get_global_ptr()->_package_host_url;
134#endif
135}
136
137/**
138 * Returns the current version of Panda's Core API, expressed as a string of
139 * dot-delimited integers. There are usually four integers in this version,
140 * but this is not guaranteed.
141 *
142 * The Core API is used during the runtime (plugin) environment only. This
143 * may be the empty string if the current version of Panda is not built to
144 * provide a particular Core API, which will be the normal case in a
145 * development SDK. However, you should not use this method to determine
146 * whether you are running in a runtime environment or not.
147 */
150#ifndef P3D_COREAPI_VERSION_STR
151 return "";
152#else
153 return P3D_COREAPI_VERSION_STR;
154#endif
155}
156
157/**
158 * Returns the major version number of the current version of Panda. This is
159 * the first number of the dotted triple returned by get_version_string(). It
160 * changes very rarely.
161 */
164 return PANDA_MAJOR_VERSION;
165}
166
167/**
168 * Returns the minor version number of the current version of Panda. This is
169 * the second number of the dotted triple returned by get_version_string().
170 * It changes with each release that introduces new features.
171 */
174 return PANDA_MINOR_VERSION;
175}
176
177/**
178 * Returns the sequence version number of the current version of Panda. This
179 * is the third number of the dotted triple returned by get_version_string().
180 * It changes with bugfix updates and very minor feature updates.
181 */
184 return PANDA_SEQUENCE_VERSION;
185}
186
187/**
188 * Returns true if current version of Panda claims to be an "official"
189 * version, that is, one that was compiled by an official distributor of Panda
190 * using a specific version of the panda source tree. If this is true, there
191 * will not be a "c" at the end of the version string returned by
192 * get_version_string().
193 *
194 * Note that we must take the distributor's word for it here.
195 */
196bool PandaSystem::
198#ifdef PANDA_OFFICIAL_VERSION
199 return true;
200#else
201 return false;
202#endif
203}
204
205/**
206 * Returns the memory alignment that Panda's allocators are using.
207 */
210 return MEMORY_HOOK_ALIGNMENT;
211}
212
213/**
214 * Returns the string defined by the distributor of this version of Panda, or
215 * "homebuilt" if this version was built directly from the sources by the end-
216 * user. This is a completely arbitrary string.
217 */
218string PandaSystem::
220 return PANDA_DISTRIBUTOR;
221}
222
223/**
224 * Returns a string representing the compiler that was used to generate this
225 * version of Panda, if it is available, or "unknown" if it is not.
226 */
227string PandaSystem::
228get_compiler() {
229#if defined(_MSC_VER)
230 // MSVC defines this macro. It's an integer; we need to format it.
231 std::ostringstream strm;
232 strm << "MSC v." << _MSC_VER;
233
234 // We also get this suite of macros that tells us what the build platform
235 // is.
236#if defined(_M_IX86)
237 #ifdef MS_WIN64
238 strm << " 64 bit (Intel)";
239 #else // MS_WIN64
240 strm << " 32 bit (Intel)";
241 #endif // MS_WIN64
242#elif defined(_M_IA64)
243 strm << " 64 bit (Itanium)";
244#elif defined(_M_AMD64)
245 strm << " 64 bit (AMD64)";
246#endif
247
248 return strm.str();
249
250#elif defined(__clang__)
251 // Clang has this macro. This case has to go before __GNUC__ because that
252 // is also defined by clang.
253 return "Clang " __clang_version__;
254
255#elif defined(__GNUC__)
256 // GCC defines this simple macro.
257 return "GCC " __VERSION__;
258
259#else
260 // For other compilers, you're on your own.
261 return "unknown";
262#endif
263}
264
265/**
266 * Returns a string representing the date and time at which this version of
267 * Panda (or at least dtool) was compiled, if available.
268 */
269string PandaSystem::
271#ifdef PANDA_BUILD_DATE_STR
272 return PANDA_BUILD_DATE_STR;
273#else
274 return __DATE__ " " __TIME__;
275#endif
276}
277
278/**
279 * Returns a string representing the git commit hash that this source tree is
280 * based on, or the empty string if it has not been specified at build time.
281 */
282string PandaSystem::
284#ifdef PANDA_GIT_COMMIT_STR
285 return PANDA_GIT_COMMIT_STR;
286#else
287 return string();
288#endif
289}
290
291/**
292 * Returns a string representing the runtime platform that we are currently
293 * running on. This will be something like "win32" or "osx_i386" or
294 * "linux_amd64".
295 */
296string PandaSystem::
297get_platform() {
298 return DTOOL_PLATFORM;
299}
300
301/**
302 * Returns true if the current version of Panda claims to have the indicated
303 * subsystem installed, false otherwise. The set of available subsystems is
304 * implementation defined.
305 */
307has_system(const string &system) const {
308 Systems::const_iterator si;
309 si = _systems.find(system);
310 return (si != _systems.end());
311}
312
313/**
314 * Returns the number of Panda subsystems that have registered themselves.
315 * This can be used with get_system() to iterate through the entire list of
316 * available Panda subsystems.
317 */
318size_t PandaSystem::
319get_num_systems() const {
320 return _systems.size();
321}
322
323/**
324 * Returns the nth Panda subsystem that has registered itself. This list will
325 * be sorted in alphabetical order.
326 */
327string PandaSystem::
328get_system(size_t n) const {
329 if (n >= _systems.size()) {
330 return string();
331 }
332
333 if (_system_names_dirty) {
334 ((PandaSystem *)this)->reset_system_names();
335 }
336
337 return _system_names[n];
338}
339
340/**
341 * Returns the value associated with the indicated tag for the given system.
342 * This provides a standard way to query each subsystem's advertised
343 * capabilities. The set of tags and values are per-system and
344 * implementation-defined.
345 *
346 * The return value is the empty string if the indicated system is undefined
347 * or if does not define the indicated tag.
348 */
350get_system_tag(const string &system, const string &tag) const {
351 Systems::const_iterator si;
352 si = _systems.find(system);
353 if (si != _systems.end()) {
354 const SystemTags &tags = (*si).second;
355 SystemTags::const_iterator ti;
356 ti = tags.find(tag);
357 if (ti != tags.end()) {
358 return (*ti).second;
359 }
360 }
361
362 return string();
363}
364
365/**
366 * Intended for use by each subsystem to register itself at startup.
367 */
369add_system(const string &system) {
370 bool inserted = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))).second;
371 if (inserted) {
372 _system_names_dirty = true;
373 }
374}
375
376/**
377 * Intended for use by each subsystem to register its set of capabilities at
378 * startup.
379 */
381set_system_tag(const string &system, const string &tag,
382 const string &value) {
383 std::pair<Systems::iterator, bool> result;
384 result = _systems.insert(Systems::value_type(system, SystemTags(get_class_type())));
385 if (result.second) {
386 _system_names_dirty = true;
387 }
388
389 SystemTags &tags = (*result.first).second;
390 tags[tag] = value;
391}
392
393/**
394 * Attempts to release memory back to the system, if possible. The pad
395 * argument is the minimum amount of unused memory to keep in the heap
396 * (against future allocations). Any memory above that may be released to the
397 * system, reducing the memory size of this process. There is no guarantee
398 * that any memory may be released.
399 *
400 * Returns true if any memory was actually released, false otherwise.
401 */
403heap_trim(size_t pad) {
404 // This actually just vectors into _memory_hook, which isn't published.
405 // This method only exists on PandaSystem for the convenience of Python
406 // programmers.
407 return memory_hook->heap_trim(pad);
408}
409
410/**
411 *
412 */
413void PandaSystem::
414output(std::ostream &out) const {
415 out << "Panda version " << get_version_string();
416}
417
418/**
419 *
420 */
421void PandaSystem::
422write(std::ostream &out) const {
423 out << *this << "\n"
424 << "compiled on " << get_build_date() << " by "
425 << get_distributor() << "\n"
426 << "with compiler " << PandaSystem::get_compiler() << "\n\n";
427
428 out << "Optional systems:\n";
429 for (Systems::const_iterator si = _systems.begin();
430 si != _systems.end();
431 ++si) {
432 out << " " << (*si).first << "\n";
433 const SystemTags &tags = (*si).second;
434 SystemTags::const_iterator ti;
435 for (ti = tags.begin(); ti != tags.end(); ++ti) {
436 out << " " << (*ti).first << " " << (*ti).second << "\n";
437 }
438 }
439}
440
441
442/**
443 * Returns the global PandaSystem object.
444 */
447 if (_global_ptr == nullptr) {
448 init_type();
449 _global_ptr = new PandaSystem;
450 }
451
452 return _global_ptr;
453}
454
455/**
456 * Refills the _system_names vector, which is used for get_system_name(), from
457 * the current set of available system names.
458 */
459void PandaSystem::
460reset_system_names() {
461 _system_names.clear();
462 _system_names.reserve(_systems.size());
463
464 Systems::const_iterator si;
465 for (si = _systems.begin(); si != _systems.end(); ++si) {
466 _system_names.push_back((*si).first);
467 }
468
469 _system_names_dirty = false;
470}
471
472/**
473 * Loads the value returned by get_package_version_string(). This is intended
474 * to be called by ConfigPageManager to preload the value from the panda-
475 * package-version config variable, for developer's convenience. This has no
476 * effect if the PANDA_PACKAGE_VERSION_STR configure variable is defined at
477 * compilation time. This also has no effect in NDEBUG mode.
478 */
479void PandaSystem::
480set_package_version_string(const string &package_version_string) {
481 _package_version_string = PANDA_PACKAGE_VERSION_STR;
482 if (_package_version_string.empty()) {
483 _package_version_string = package_version_string;
484 }
485}
486
487/**
488 * Loads the value returned by get_package_host_url(). This is intended to be
489 * called by ConfigPageManager to preload the value from the panda-package-
490 * host-url config variable, for developer's convenience. This has no effect
491 * if the PANDA_PACKAGE_HOST_URL configure variable is defined at compilation
492 * time. This also has no effect in NDEBUG mode.
493 */
494void PandaSystem::
495set_package_host_url(const string &package_host_url) {
496 _package_host_url = PANDA_PACKAGE_HOST_URL;
497 if (_package_host_url.empty()) {
498 _package_host_url = package_host_url;
499 }
500}
bool heap_trim(size_t pad)
Attempts to release memory back to the system, if possible.
Definition: memoryHook.cxx:476
This class is used as a namespace to group several global properties of Panda.
Definition: pandaSystem.h:26
get_num_systems
Returns the number of Panda subsystems that have registered themselves.
Definition: pandaSystem.h:69
get_sequence_version
Returns the sequence version number of the current version of Panda.
Definition: pandaSystem.h:54
get_build_date
Returns a string representing the date and time at which this version of Panda (or at least dtool) wa...
Definition: pandaSystem.h:61
is_official_version
Returns true if current version of Panda claims to be an "official" version, that is,...
Definition: pandaSystem.h:55
get_system
Returns the nth Panda subsystem that has registered itself.
Definition: pandaSystem.h:69
void set_system_tag(const std::string &system, const std::string &tag, const std::string &value)
Intended for use by each subsystem to register its set of capabilities at startup.
get_major_version
Returns the major version number of the current version of Panda.
Definition: pandaSystem.h:52
get_platform
Returns a string representing the runtime platform that we are currently running on.
Definition: pandaSystem.h:64
get_memory_alignment
Returns the memory alignment that Panda's allocators are using.
Definition: pandaSystem.h:57
get_version_string
Returns the current version of Panda, expressed as a string, e.g.
Definition: pandaSystem.h:51
get_git_commit
Returns a string representing the git commit hash that this source tree is based on,...
Definition: pandaSystem.h:62
static std::string get_package_host_url()
Returns the URL of the download server that provides the Panda3D distributable package currently runn...
get_minor_version
Returns the minor version number of the current version of Panda.
Definition: pandaSystem.h:53
get_distributor
Returns the string defined by the distributor of this version of Panda, or "homebuilt" if this versio...
Definition: pandaSystem.h:59
get_compiler
Returns a string representing the compiler that was used to generate this version of Panda,...
Definition: pandaSystem.h:60
static PandaSystem * get_global_ptr()
Returns the global PandaSystem object.
static std::string get_p3d_coreapi_version_string()
Returns the current version of Panda's Core API, expressed as a string of dot-delimited integers.
void add_system(const std::string &system)
Intended for use by each subsystem to register itself at startup.
bool has_system(const std::string &system) const
Returns true if the current version of Panda claims to have the indicated subsystem installed,...
std::string get_system_tag(const std::string &system, const std::string &tag) const
Returns the value associated with the indicated tag for the given system.
static std::string get_package_version_string()
Returns the version of the Panda3D distributable package that provides this build of Panda.
bool heap_trim(size_t pad)
Attempts to release memory back to the system, if possible.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.