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 
18 using std::string;
19 
20 PandaSystem *PandaSystem::_global_ptr = nullptr;
21 TypeHandle 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  */
28 PandaSystem::
29 PandaSystem() :
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  */
75 PandaSystem::
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  */
84 string 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  */
162 int PandaSystem::
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  */
172 int PandaSystem::
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  */
182 int PandaSystem::
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  */
196 bool 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  */
208 int PandaSystem::
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  */
218 string PandaSystem::
219 get_distributor() {
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  */
227 string PandaSystem::
228 get_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  */
269 string PandaSystem::
270 get_build_date() {
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  */
282 string PandaSystem::
283 get_git_commit() {
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  */
296 string PandaSystem::
297 get_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  */
307 has_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  */
318 size_t PandaSystem::
319 get_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  */
327 string PandaSystem::
328 get_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  */
350 get_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  */
369 add_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  */
381 set_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  */
403 heap_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  */
413 void PandaSystem::
414 output(std::ostream &out) const {
415  out << "Panda version " << get_version_string();
416 }
417 
418 /**
419  *
420  */
421 void PandaSystem::
422 write(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  */
446 get_global_ptr() {
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  */
459 void PandaSystem::
460 reset_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  */
479 void PandaSystem::
480 set_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  */
494 void PandaSystem::
495 set_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.