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  return __DATE__ " " __TIME__;
272 }
273 
274 /**
275  * Returns a string representing the git commit hash that this source tree is
276  * based on, or the empty string if it has not been specified at build time.
277  */
278 string PandaSystem::
279 get_git_commit() {
280 #ifdef PANDA_GIT_COMMIT_STR
281  return PANDA_GIT_COMMIT_STR;
282 #else
283  return string();
284 #endif
285 }
286 
287 /**
288  * Returns a string representing the runtime platform that we are currently
289  * running on. This will be something like "win32" or "osx_i386" or
290  * "linux_amd64".
291  */
292 string PandaSystem::
293 get_platform() {
294  return DTOOL_PLATFORM;
295 }
296 
297 /**
298  * Returns true if the current version of Panda claims to have the indicated
299  * subsystem installed, false otherwise. The set of available subsystems is
300  * implementation defined.
301  */
303 has_system(const string &system) const {
304  Systems::const_iterator si;
305  si = _systems.find(system);
306  return (si != _systems.end());
307 }
308 
309 /**
310  * Returns the number of Panda subsystems that have registered themselves.
311  * This can be used with get_system() to iterate through the entire list of
312  * available Panda subsystems.
313  */
314 size_t PandaSystem::
315 get_num_systems() const {
316  return _systems.size();
317 }
318 
319 /**
320  * Returns the nth Panda subsystem that has registered itself. This list will
321  * be sorted in alphabetical order.
322  */
323 string PandaSystem::
324 get_system(size_t n) const {
325  if (n >= _systems.size()) {
326  return string();
327  }
328 
329  if (_system_names_dirty) {
330  ((PandaSystem *)this)->reset_system_names();
331  }
332 
333  return _system_names[n];
334 }
335 
336 /**
337  * Returns the value associated with the indicated tag for the given system.
338  * This provides a standard way to query each subsystem's advertised
339  * capabilities. The set of tags and values are per-system and
340  * implementation-defined.
341  *
342  * The return value is the empty string if the indicated system is undefined
343  * or if does not define the indicated tag.
344  */
346 get_system_tag(const string &system, const string &tag) const {
347  Systems::const_iterator si;
348  si = _systems.find(system);
349  if (si != _systems.end()) {
350  const SystemTags &tags = (*si).second;
351  SystemTags::const_iterator ti;
352  ti = tags.find(tag);
353  if (ti != tags.end()) {
354  return (*ti).second;
355  }
356  }
357 
358  return string();
359 }
360 
361 /**
362  * Intended for use by each subsystem to register itself at startup.
363  */
365 add_system(const string &system) {
366  bool inserted = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))).second;
367  if (inserted) {
368  _system_names_dirty = true;
369  }
370 }
371 
372 /**
373  * Intended for use by each subsystem to register its set of capabilities at
374  * startup.
375  */
377 set_system_tag(const string &system, const string &tag,
378  const string &value) {
379  std::pair<Systems::iterator, bool> result;
380  result = _systems.insert(Systems::value_type(system, SystemTags(get_class_type())));
381  if (result.second) {
382  _system_names_dirty = true;
383  }
384 
385  SystemTags &tags = (*result.first).second;
386  tags[tag] = value;
387 }
388 
389 /**
390  * Attempts to release memory back to the system, if possible. The pad
391  * argument is the minimum amount of unused memory to keep in the heap
392  * (against future allocations). Any memory above that may be released to the
393  * system, reducing the memory size of this process. There is no guarantee
394  * that any memory may be released.
395  *
396  * Returns true if any memory was actually released, false otherwise.
397  */
399 heap_trim(size_t pad) {
400  // This actually just vectors into _memory_hook, which isn't published.
401  // This method only exists on PandaSystem for the convenience of Python
402  // programmers.
403  return memory_hook->heap_trim(pad);
404 }
405 
406 /**
407  *
408  */
409 void PandaSystem::
410 output(std::ostream &out) const {
411  out << "Panda version " << get_version_string();
412 }
413 
414 /**
415  *
416  */
417 void PandaSystem::
418 write(std::ostream &out) const {
419  out << *this << "\n"
420  << "compiled on " << get_build_date() << " by "
421  << get_distributor() << "\n"
422  << "with compiler " << PandaSystem::get_compiler() << "\n\n";
423 
424  out << "Optional systems:\n";
425  for (Systems::const_iterator si = _systems.begin();
426  si != _systems.end();
427  ++si) {
428  out << " " << (*si).first << "\n";
429  const SystemTags &tags = (*si).second;
430  SystemTags::const_iterator ti;
431  for (ti = tags.begin(); ti != tags.end(); ++ti) {
432  out << " " << (*ti).first << " " << (*ti).second << "\n";
433  }
434  }
435 }
436 
437 
438 /**
439  * Returns the global PandaSystem object.
440  */
442 get_global_ptr() {
443  if (_global_ptr == nullptr) {
444  init_type();
445  _global_ptr = new PandaSystem;
446  }
447 
448  return _global_ptr;
449 }
450 
451 /**
452  * Refills the _system_names vector, which is used for get_system_name(), from
453  * the current set of available system names.
454  */
455 void PandaSystem::
456 reset_system_names() {
457  _system_names.clear();
458  _system_names.reserve(_systems.size());
459 
460  Systems::const_iterator si;
461  for (si = _systems.begin(); si != _systems.end(); ++si) {
462  _system_names.push_back((*si).first);
463  }
464 
465  _system_names_dirty = false;
466 }
467 
468 /**
469  * Loads the value returned by get_package_version_string(). This is intended
470  * to be called by ConfigPageManager to preload the value from the panda-
471  * package-version config variable, for developer's convenience. This has no
472  * effect if the PANDA_PACKAGE_VERSION_STR configure variable is defined at
473  * compilation time. This also has no effect in NDEBUG mode.
474  */
475 void PandaSystem::
476 set_package_version_string(const string &package_version_string) {
477  _package_version_string = PANDA_PACKAGE_VERSION_STR;
478  if (_package_version_string.empty()) {
479  _package_version_string = package_version_string;
480  }
481 }
482 
483 /**
484  * Loads the value returned by get_package_host_url(). This is intended to be
485  * called by ConfigPageManager to preload the value from the panda-package-
486  * host-url config variable, for developer's convenience. This has no effect
487  * if the PANDA_PACKAGE_HOST_URL configure variable is defined at compilation
488  * time. This also has no effect in NDEBUG mode.
489  */
490 void PandaSystem::
491 set_package_host_url(const string &package_host_url) {
492  _package_host_url = PANDA_PACKAGE_HOST_URL;
493  if (_package_host_url.empty()) {
494  _package_host_url = package_host_url;
495  }
496 }
PandaSystem::get_build_date
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
PandaSystem::get_global_ptr
static PandaSystem * get_global_ptr()
Returns the global PandaSystem object.
Definition: pandaSystem.cxx:442
PandaSystem::get_platform
get_platform
Returns a string representing the runtime platform that we are currently running on.
Definition: pandaSystem.h:64
PandaSystem::get_major_version
get_major_version
Returns the major version number of the current version of Panda.
Definition: pandaSystem.h:52
pmap< std::string, std::string >
PandaSystem::get_package_version_string
static std::string get_package_version_string()
Returns the version of the Panda3D distributable package that provides this build of Panda.
Definition: pandaSystem.cxx:108
PandaSystem::get_p3d_coreapi_version_string
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.
Definition: pandaSystem.cxx:149
MemoryHook::heap_trim
bool heap_trim(size_t pad)
Attempts to release memory back to the system, if possible.
Definition: memoryHook.cxx:476
PandaSystem::get_compiler
get_compiler
Returns a string representing the compiler that was used to generate this version of Panda,...
Definition: pandaSystem.h:60
PandaSystem
This class is used as a namespace to group several global properties of Panda.
Definition: pandaSystem.h:26
PandaSystem::get_memory_alignment
get_memory_alignment
Returns the memory alignment that Panda's allocators are using.
Definition: pandaSystem.h:57
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PandaSystem::get_git_commit
get_git_commit
Returns a string representing the git commit hash that this source tree is based on,...
Definition: pandaSystem.h:62
PandaSystem::get_system_tag
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.
Definition: pandaSystem.cxx:346
PandaSystem::heap_trim
bool heap_trim(size_t pad)
Attempts to release memory back to the system, if possible.
Definition: pandaSystem.cxx:399
PandaSystem::add_system
void add_system(const std::string &system)
Intended for use by each subsystem to register itself at startup.
Definition: pandaSystem.cxx:365
PandaSystem::get_sequence_version
get_sequence_version
Returns the sequence version number of the current version of Panda.
Definition: pandaSystem.h:54
pandaSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaSystem::has_system
bool has_system(const std::string &system) const
Returns true if the current version of Panda claims to have the indicated subsystem installed,...
Definition: pandaSystem.cxx:303
PandaSystem::get_system
get_system
Returns the nth Panda subsystem that has registered itself.
Definition: pandaSystem.h:69
PandaSystem::get_num_systems
get_num_systems
Returns the number of Panda subsystems that have registered themselves.
Definition: pandaSystem.h:69
PandaSystem::get_minor_version
get_minor_version
Returns the minor version number of the current version of Panda.
Definition: pandaSystem.h:53
PandaSystem::get_package_host_url
static std::string get_package_host_url()
Returns the URL of the download server that provides the Panda3D distributable package currently runn...
Definition: pandaSystem.cxx:129
dtool_platform.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaSystem::set_system_tag
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.
Definition: pandaSystem.cxx:377
PandaSystem::is_official_version
is_official_version
Returns true if current version of Panda claims to be an "official" version, that is,...
Definition: pandaSystem.h:55
PandaSystem::get_distributor
get_distributor
Returns the string defined by the distributor of this version of Panda, or "homebuilt" if this versio...
Definition: pandaSystem.h:59
PandaSystem::get_version_string
get_version_string
Returns the current version of Panda, expressed as a string, e.g.
Definition: pandaSystem.h:51