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