Panda3D
 All Classes Functions Variables Enumerations
pandaSystem.cxx
00001 // Filename: pandaSystem.cxx
00002 // Created by:  drose (26Jan05)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pandaSystem.h"
00016 #include "pandaVersion.h"
00017 #include "dtool_platform.h"
00018 
00019 PandaSystem *PandaSystem::_global_ptr = NULL;
00020 TypeHandle PandaSystem::_type_handle;
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 //     Function: PandaSystem::Constructor
00024 //       Access: Protected
00025 //  Description: Don't try to construct a PandaSystem object; there is
00026 //               only one of these, and it constructs itself.  Use
00027 //               get_global_ptr() to get a pointer to the one
00028 //               PandaSystem.
00029 ////////////////////////////////////////////////////////////////////
00030 PandaSystem::
00031 PandaSystem() :
00032   _systems(get_class_type())
00033 {
00034   _system_names_dirty = false;
00035 
00036   // These are settable via Config.prc, but only in development
00037   // (!NDEBUG) mode, and only if they are not already defined.
00038   _package_version_string = PANDA_PACKAGE_VERSION_STR;
00039   _package_host_url = PANDA_PACKAGE_HOST_URL;
00040 
00041 #ifdef STDFLOAT_DOUBLE
00042   add_system("stdfloat-double");
00043 #endif
00044 
00045 #ifdef HAVE_EIGEN
00046   add_system("eigen");
00047 #ifdef LINMATH_ALIGN
00048   set_system_tag("eigen", "vectorize", "1");
00049 #else
00050   set_system_tag("eigen", "vectorize", "0");
00051 #endif
00052 #endif  // HAVE_EIGEN
00053 
00054 #ifdef USE_MEMORY_DLMALLOC
00055   set_system_tag("system", "malloc", "dlmalloc");
00056 #elif defined(USE_MEMORY_PTMALLOC2)
00057   set_system_tag("system", "malloc", "ptmalloc2");
00058 #else
00059   set_system_tag("system", "malloc", "malloc");
00060 #endif
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: PandaSystem::Destructor
00065 //       Access: Protected
00066 //  Description: Don't try to destruct the global PandaSystem object.
00067 ////////////////////////////////////////////////////////////////////
00068 PandaSystem::
00069 ~PandaSystem() {
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: PandaSystem::get_version_string
00074 //       Access: Published, Static
00075 //  Description: Returns the current version of Panda, expressed as a
00076 //               string, e.g. "1.0.0".  The string will end in the
00077 //               letter "c" if this build does not represent an
00078 //               official version.
00079 ////////////////////////////////////////////////////////////////////
00080 string PandaSystem::
00081 get_version_string() {
00082   return PANDA_VERSION_STR;
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: PandaSystem::get_package_version_string
00087 //       Access: Published, Static
00088 //  Description: Returns the version of the Panda3D distributable
00089 //               package that provides this build of Panda.
00090 //
00091 //               When the currently-executing version of Panda was
00092 //               loaded from a distributable package, such as via the
00093 //               browser plugin, then this string will be nonempty and
00094 //               will contain the corresponding version string.  You
00095 //               can build applications that use this particular
00096 //               version of Panda by requesting it in the pdef file,
00097 //               using "panda3d", this version string, and the
00098 //               download host provided by get_package_host_url().
00099 //
00100 //               If this string is empty, then the currently-executing
00101 //               Panda was built independently, and is not part of a
00102 //               distributable package.
00103 //
00104 //               This string is set explicitly at compilation time.
00105 //               Normally, it should be set to a nonempty string only
00106 //               when building a Panda3D package for distribution.
00107 ////////////////////////////////////////////////////////////////////
00108 string PandaSystem::
00109 get_package_version_string() {
00110 #ifdef NDEBUG
00111   return PANDA_PACKAGE_VERSION_STR;
00112 #else
00113   return get_global_ptr()->_package_version_string;
00114 #endif
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: PandaSystem::get_package_host_url
00119 //       Access: Published, Static
00120 //  Description: Returns the URL of the download server that provides
00121 //               the Panda3D distributable package currently running.
00122 //               This can be used, along with the
00123 //               get_package_version_string(), to uniquely identify
00124 //               the running version of Panda among distributable
00125 //               Panda versions.
00126 //
00127 //               See get_package_version_string() for more information.
00128 //
00129 //               This string is set explicitly at compilation time.
00130 //               Normally, it should be set to a nonempty string only
00131 //               when building a Panda3D package for distribution.
00132 ////////////////////////////////////////////////////////////////////
00133 string PandaSystem::
00134 get_package_host_url() {
00135 #ifdef NDEBUG
00136   return PANDA_PACKAGE_HOST_URL;
00137 #else
00138   return get_global_ptr()->_package_host_url;
00139 #endif
00140 }
00141 
00142 ////////////////////////////////////////////////////////////////////
00143 //     Function: PandaSystem::get_p3d_coreapi_version_string
00144 //       Access: Published, Static
00145 //  Description: Returns the current version of Panda's Core API,
00146 //               expressed as a string of dot-delimited integers.
00147 //               There are usually four integers in this version, but
00148 //               this is not guaranteed.
00149 //
00150 //               The Core API is used during the runtime (plugin)
00151 //               environment only.  This may be the empty string if
00152 //               the current version of Panda is not built to provide
00153 //               a particular Core API, which will be the normal case
00154 //               in a development SDK.  However, you should not use
00155 //               this method to determine whether you are running in a
00156 //               runtime environment or not.
00157 ////////////////////////////////////////////////////////////////////
00158 string PandaSystem::
00159 get_p3d_coreapi_version_string() {
00160 #ifndef P3D_COREAPI_VERSION_STR
00161   return "";
00162 #else
00163   return P3D_COREAPI_VERSION_STR;
00164 #endif
00165 }
00166 
00167 ////////////////////////////////////////////////////////////////////
00168 //     Function: PandaSystem::get_major_version
00169 //       Access: Published, Static
00170 //  Description: Returns the major version number of the current
00171 //               version of Panda.  This is the first number of the
00172 //               dotted triple returned by get_version_string().  It
00173 //               changes very rarely.
00174 ////////////////////////////////////////////////////////////////////
00175 int PandaSystem::
00176 get_major_version() {
00177   return PANDA_MAJOR_VERSION;
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: PandaSystem::get_minor_version
00182 //       Access: Published, Static
00183 //  Description: Returns the minor version number of the current
00184 //               version of Panda.  This is the second number of the
00185 //               dotted triple returned by get_version_string().  It
00186 //               changes with each release that introduces new
00187 //               features.
00188 ////////////////////////////////////////////////////////////////////
00189 int PandaSystem::
00190 get_minor_version() {
00191   return PANDA_MINOR_VERSION;
00192 }
00193 
00194 ////////////////////////////////////////////////////////////////////
00195 //     Function: PandaSystem::get_sequence_version
00196 //       Access: Published, Static
00197 //  Description: Returns the sequence version number of the current
00198 //               version of Panda.  This is the third number of the
00199 //               dotted triple returned by get_version_string().  It
00200 //               changes with bugfix updates and very minor feature
00201 //               updates.
00202 ////////////////////////////////////////////////////////////////////
00203 int PandaSystem::
00204 get_sequence_version() {
00205   return PANDA_SEQUENCE_VERSION;
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: PandaSystem::is_official_version
00210 //       Access: Published, Static
00211 //  Description: Returns true if current version of Panda claims to be
00212 //               an "official" version, that is, one that was compiled
00213 //               by an official distributor of Panda using a specific
00214 //               version of the panda source tree.  If this is true,
00215 //               there will not be a "c" at the end of the version
00216 //               string returned by get_version_string().
00217 //
00218 //               Note that we must take the distributor's word for it
00219 //               here.
00220 ////////////////////////////////////////////////////////////////////
00221 bool PandaSystem::
00222 is_official_version() {
00223 #ifdef PANDA_OFFICIAL_VERSION
00224   return true;
00225 #else
00226   return false;
00227 #endif
00228 }
00229   
00230 ////////////////////////////////////////////////////////////////////
00231 //     Function: PandaSystem::get_distributor
00232 //       Access: Published, Static
00233 //  Description: Returns the string defined by the distributor of this
00234 //               version of Panda, or "homebuilt" if this version was
00235 //               built directly from the sources by the end-user.
00236 //               This is a completely arbitrary string.
00237 ////////////////////////////////////////////////////////////////////
00238 string PandaSystem::
00239 get_distributor() {
00240   return PANDA_DISTRIBUTOR;
00241 }
00242   
00243 ////////////////////////////////////////////////////////////////////
00244 //     Function: PandaSystem::get_compiler
00245 //       Access: Published, Static
00246 //  Description: Returns a string representing the compiler that was
00247 //               used to generate this version of Panda, if it is
00248 //               available, or "unknown" if it is not.
00249 ////////////////////////////////////////////////////////////////////
00250 string PandaSystem::
00251 get_compiler() {
00252 #if defined(_MSC_VER)
00253   // MSVC defines this macro.  It's an integer; we need to format it.
00254   ostringstream strm;
00255   strm << "MSC v." << _MSC_VER;
00256 
00257   // We also get this suite of macros that tells us what the build
00258   // platform is.
00259 #if defined(_M_IX86)
00260   #ifdef MS_WIN64
00261   strm << " 64 bit (Intel)";
00262   #else  // MS_WIN64
00263   strm << " 32 bit (Intel)";
00264   #endif  // MS_WIN64
00265 #elif defined(_M_IA64)
00266   strm << " 64 bit (Itanium)";
00267 #elif defined(_M_AMD64)
00268   strm << " 64 bit (AMD64)";
00269 #endif
00270 
00271   return strm.str();
00272 
00273 #elif defined(__GNUC__)
00274   // GCC defines this simple macro.
00275   return "GCC " __VERSION__;
00276 
00277 #else
00278   // For other compilers, you're on your own.
00279   return "unknown";
00280 #endif
00281 }
00282   
00283 ////////////////////////////////////////////////////////////////////
00284 //     Function: PandaSystem::get_build_date
00285 //       Access: Published, Static
00286 //  Description: Returns a string representing the date and time at
00287 //               which this version of Panda (or at least dtool) was
00288 //               compiled, if available.
00289 ////////////////////////////////////////////////////////////////////
00290 string PandaSystem::
00291 get_build_date() {
00292   return __DATE__ " " __TIME__;
00293 }
00294   
00295 ////////////////////////////////////////////////////////////////////
00296 //     Function: PandaSystem::get_platform
00297 //       Access: Published, Static
00298 //  Description: Returns a string representing the runtime platform
00299 //               that we are currently running on.  This will be
00300 //               something like "win32" or "osx.i386" or
00301 //               "linux.amd64".
00302 ////////////////////////////////////////////////////////////////////
00303 string PandaSystem::
00304 get_platform() {
00305   return DTOOL_PLATFORM;
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: PandaSystem::has_system
00310 //       Access: Published
00311 //  Description: Returns true if the current version of Panda claims
00312 //               to have the indicated subsystem installed, false
00313 //               otherwise.  The set of available subsystems is
00314 //               implementation defined.
00315 ////////////////////////////////////////////////////////////////////
00316 bool PandaSystem::
00317 has_system(const string &system) const {
00318   Systems::const_iterator si;
00319   si = _systems.find(system);
00320   return (si != _systems.end());
00321 }
00322 
00323 ////////////////////////////////////////////////////////////////////
00324 //     Function: PandaSystem::get_num_systems
00325 //       Access: Published
00326 //  Description: Returns the number of Panda subsystems that have
00327 //               registered themselves.  This can be used with
00328 //               get_system() to iterate through the entire list of
00329 //               available Panda subsystems.
00330 ////////////////////////////////////////////////////////////////////
00331 int PandaSystem::
00332 get_num_systems() const {
00333   return _systems.size();
00334 }
00335 
00336 ////////////////////////////////////////////////////////////////////
00337 //     Function: PandaSystem::get_system
00338 //       Access: Published
00339 //  Description: Returns the nth Panda subsystem that has registered
00340 //               itself.  This list will be sorted in alphabetical
00341 //               order.
00342 ////////////////////////////////////////////////////////////////////
00343 string PandaSystem::
00344 get_system(int n) const {
00345   if (n < 0 || n >= (int)_systems.size()) {
00346     return string();
00347   }
00348 
00349   if (_system_names_dirty) {
00350     ((PandaSystem *)this)->reset_system_names();
00351   }
00352 
00353   return _system_names[n];
00354 }
00355 
00356 ////////////////////////////////////////////////////////////////////
00357 //     Function: PandaSystem::get_system_tag
00358 //       Access: Published
00359 //  Description: Returns the value associated with the indicated tag
00360 //               for the given system.  This provides a standard way
00361 //               to query each subsystem's advertised capabilities.
00362 //               The set of tags and values are per-system and
00363 //               implementation-defined.
00364 //
00365 //               The return value is the empty string if the indicated
00366 //               system is undefined or if does not define the
00367 //               indicated tag.
00368 ////////////////////////////////////////////////////////////////////
00369 string PandaSystem::
00370 get_system_tag(const string &system, const string &tag) const {
00371   Systems::const_iterator si;
00372   si = _systems.find(system);
00373   if (si != _systems.end()) {
00374     const SystemTags &tags = (*si).second;
00375     SystemTags::const_iterator ti;
00376     ti = tags.find(tag);
00377     if (ti != tags.end()) {
00378       return (*ti).second;
00379     }
00380   }
00381 
00382   return string();
00383 }
00384 
00385 ////////////////////////////////////////////////////////////////////
00386 //     Function: PandaSystem::add_system
00387 //       Access: Published
00388 //  Description: Intended for use by each subsystem to register itself
00389 //               at startup.
00390 ////////////////////////////////////////////////////////////////////
00391 void PandaSystem::
00392 add_system(const string &system) {
00393   bool inserted = _systems.insert(Systems::value_type(system, SystemTags(get_class_type()))).second;
00394   if (inserted) {
00395     _system_names_dirty = true;
00396   }
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: PandaSystem::set_system_tag
00401 //       Access: Published
00402 //  Description: Intended for use by each subsystem to register its
00403 //               set of capabilities at startup.
00404 ////////////////////////////////////////////////////////////////////
00405 void PandaSystem::
00406 set_system_tag(const string &system, const string &tag,
00407                const string &value) {
00408   pair<Systems::iterator, bool> result;
00409   result = _systems.insert(Systems::value_type(system, SystemTags(get_class_type())));
00410   if (result.second) {
00411     _system_names_dirty = true;
00412   }
00413 
00414   SystemTags &tags = (*result.first).second;
00415   tags[tag] = value;
00416 }
00417 
00418 ////////////////////////////////////////////////////////////////////
00419 //     Function: PandaSystem::heap_trim
00420 //       Access: Published
00421 //  Description: Attempts to release memory back to the system, if
00422 //               possible.  The pad argument is the minimum amount of
00423 //               unused memory to keep in the heap (against future
00424 //               allocations).  Any memory above that may be released
00425 //               to the system, reducing the memory size of this
00426 //               process.  There is no guarantee that any memory may
00427 //               be released.
00428 //
00429 //               Returns true if any memory was actually released,
00430 //               false otherwise.
00431 ////////////////////////////////////////////////////////////////////
00432 bool PandaSystem::
00433 heap_trim(size_t pad) {
00434   // This actually just vectors into _memory_hook, which isn't
00435   // published.  This method only exists on PandaSystem for the
00436   // convenience of Python programmers.
00437   return memory_hook->heap_trim(pad);
00438 }
00439 
00440 ////////////////////////////////////////////////////////////////////
00441 //     Function: PandaSystem::output
00442 //       Access: Published
00443 //  Description: 
00444 ////////////////////////////////////////////////////////////////////
00445 void PandaSystem::
00446 output(ostream &out) const {
00447   out << "Panda version " << get_version_string();
00448 }
00449 
00450 ////////////////////////////////////////////////////////////////////
00451 //     Function: PandaSystem::write
00452 //       Access: Published
00453 //  Description: 
00454 ////////////////////////////////////////////////////////////////////
00455 void PandaSystem::
00456 write(ostream &out) const {
00457   out << *this << "\n"
00458       << "compiled on " << get_build_date() << " by "
00459       << get_distributor() << "\n"
00460       << "with compiler " << PandaSystem::get_compiler() << "\n\n";
00461 
00462   out << "Optional systems:\n";
00463   for (Systems::const_iterator si = _systems.begin();
00464        si != _systems.end();
00465        ++si) {
00466     out << "  " << (*si).first << "\n";
00467     const SystemTags &tags = (*si).second;
00468     SystemTags::const_iterator ti;
00469     for (ti = tags.begin(); ti != tags.end(); ++ti) {
00470       out << "    " << (*ti).first << " " << (*ti).second << "\n";
00471     }
00472   }
00473 }
00474 
00475   
00476 ////////////////////////////////////////////////////////////////////
00477 //     Function: PandaSystem::get_global_ptr
00478 //       Access: Published, Static
00479 //  Description: Returns the global PandaSystem object.
00480 ////////////////////////////////////////////////////////////////////
00481 PandaSystem *PandaSystem::
00482 get_global_ptr() {
00483   if (_global_ptr == (PandaSystem *)NULL) {
00484     _global_ptr = new PandaSystem;
00485   }
00486 
00487   return _global_ptr;
00488 }
00489 
00490 ////////////////////////////////////////////////////////////////////
00491 //     Function: PandaSystem::reset_system_names
00492 //       Access: Private
00493 //  Description: Refills the _system_names vector, which is used for
00494 //               get_system_name(), from the current set of available
00495 //               system names.
00496 ////////////////////////////////////////////////////////////////////
00497 void PandaSystem::
00498 reset_system_names() {
00499   _system_names.clear();
00500   _system_names.reserve(_systems.size());
00501   
00502   Systems::const_iterator si;
00503   for (si = _systems.begin(); si != _systems.end(); ++si) {
00504     _system_names.push_back((*si).first);
00505   }
00506   
00507   _system_names_dirty = false;
00508 }
00509 
00510 ////////////////////////////////////////////////////////////////////
00511 //     Function: PandaSystem::set_package_version_string
00512 //       Access: Private
00513 //  Description: Loads the value returned by
00514 //               get_package_version_string().  This is intended to be
00515 //               called by ConfigPageManager to preload the value from
00516 //               the panda-package-version config variable, for
00517 //               developer's convenience.  This has no effect if the
00518 //               PANDA_PACKAGE_VERSION_STR configure variable is
00519 //               defined at compilation time.  This also has no effect
00520 //               in NDEBUG mode.
00521 ////////////////////////////////////////////////////////////////////
00522 void PandaSystem::
00523 set_package_version_string(const string &package_version_string) {
00524   _package_version_string = PANDA_PACKAGE_VERSION_STR;
00525   if (_package_version_string.empty()) {
00526     _package_version_string = package_version_string;
00527   }
00528 }
00529 
00530 ////////////////////////////////////////////////////////////////////
00531 //     Function: PandaSystem::set_package_host_url
00532 //       Access: Private
00533 //  Description: Loads the value returned by
00534 //               get_package_host_url().  This is intended to be
00535 //               called by ConfigPageManager to preload the value from
00536 //               the panda-package-host-url config variable, for
00537 //               developer's convenience.  This has no effect if the
00538 //               PANDA_PACKAGE_HOST_URL configure variable is defined
00539 //               at compilation time.  This also has no effect in
00540 //               NDEBUG mode.
00541 ////////////////////////////////////////////////////////////////////
00542 void PandaSystem::
00543 set_package_host_url(const string &package_host_url) {
00544   _package_host_url = PANDA_PACKAGE_HOST_URL;
00545   if (_package_host_url.empty()) {
00546     _package_host_url = package_host_url;
00547   }
00548 }
 All Classes Functions Variables Enumerations