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