static-init-safe filename initializers

This commit is contained in:
David Rose 2009-04-18 00:51:03 +00:00
parent f44857f8ee
commit 4dc60ab611
2 changed files with 120 additions and 100 deletions

View File

@ -17,6 +17,7 @@
#include "dSearchPath.h" #include "dSearchPath.h"
#include "executionEnvironment.h" #include "executionEnvironment.h"
#include "vector_string.h" #include "vector_string.h"
#include "atomicAdjust.h"
#include <stdio.h> // For rename() and tempnam() #include <stdio.h> // For rename() and tempnam()
#include <time.h> // for clock() and time() #include <time.h> // for clock() and time()
@ -48,16 +49,11 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
bool Filename::_got_home_directory; Filename *Filename::_home_directory;
Filename Filename::_home_directory; Filename *Filename::_temp_directory;
bool Filename::_got_temp_directory; Filename *Filename::_app_directory;
Filename Filename::_temp_directory; Filename *Filename::_user_appdata_directory;
bool Filename::_got_app_directory; Filename *Filename::_common_appdata_directory;
Filename Filename::_app_directory;
bool Filename::_got_user_appdata_directory;
Filename Filename::_user_appdata_directory;
bool Filename::_got_common_appdata_directory;
Filename Filename::_common_appdata_directory;
TypeHandle Filename::_type_handle; TypeHandle Filename::_type_handle;
#ifdef WIN32 #ifdef WIN32
@ -454,51 +450,57 @@ temporary(const string &dirname, const string &prefix, const string &suffix,
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_home_directory() { get_home_directory() {
if (!_got_home_directory) { if (AtomicAdjust::get_ptr(_home_directory) == NULL) {
Filename home_directory;
// In all environments, check $HOME first. // In all environments, check $HOME first.
char *home = getenv("HOME"); char *home = getenv("HOME");
if (home != (char *)NULL) { if (home != (char *)NULL) {
_home_directory = from_os_specific(home); Filename dirname = from_os_specific(home);
if (_home_directory.is_directory()) { if (dirname.is_directory()) {
if (_home_directory.make_canonical()) { if (dirname.make_canonical()) {
_got_home_directory = true; home_directory = dirname;
} }
} }
} }
if (_got_home_directory) {
return _home_directory;
}
if (home_directory.empty()) {
#ifdef WIN32 #ifdef WIN32
char buffer[MAX_PATH]; char buffer[MAX_PATH];
// On Windows, fall back to the "My Documents" folder. // On Windows, fall back to the "My Documents" folder.
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_PERSONAL, true)) { if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_PERSONAL, true)) {
_user_appdata_directory = from_os_specific(buffer); Filename dirname = from_os_specific(buffer);
if (_user_appdata_directory.is_directory()) { if (dirname.is_directory()) {
if (_user_appdata_directory.make_canonical()) { if (dirname.make_canonical()) {
_got_user_appdata_directory = true; home_directory = dirname;
}
} }
} }
}
#elif defined(IS_OSX) #elif defined(IS_OSX)
_home_directory = get_osx_home_directory(); home_directory = get_osx_home_directory();
_got_home_directory = true;
#else #else
// Posix case: check /etc/passwd? // Posix case: check /etc/passwd?
#endif // WIN32 #endif // WIN32
}
if (!_got_home_directory) { if (home_directory.empty()) {
// Fallback case. // Fallback case.
_home_directory = ExecutionEnvironment::get_cwd(); home_directory = ExecutionEnvironment::get_cwd();
_got_home_directory = true; }
Filename *newdir = new Filename(home_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_home_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else.
assert(_home_directory != NULL);
delete newdir;
} }
} }
return _home_directory; return (*_home_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -509,37 +511,43 @@ get_home_directory() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_temp_directory() { get_temp_directory() {
if (!_got_temp_directory) { if (AtomicAdjust::get_ptr(_temp_directory) == NULL) {
Filename temp_directory;
#ifdef WIN32 #ifdef WIN32
static const size_t buffer_size = 4096; static const size_t buffer_size = 4096;
char buffer[buffer_size]; char buffer[buffer_size];
if (GetTempPath(buffer_size, buffer) != 0) { if (GetTempPath(buffer_size, buffer) != 0) {
_temp_directory = from_os_specific(buffer); Filename dirname = from_os_specific(buffer);
if (_temp_directory.is_directory()) { if (dirname.is_directory()) {
if (_temp_directory.make_canonical()) { if (dirname.make_canonical()) {
_got_temp_directory = true; temp_directory = dirname;
} }
} }
} }
#elif defined(IS_OSX) #elif defined(IS_OSX)
_temp_directory = get_osx_temp_directory(); temp_directory = get_osx_temp_directory();
_got_temp_directory = true;
#else #else
// Posix case. // Posix case.
_temp_directory = "/tmp"; temp_directory = "/tmp";
_got_temp_directory = true;
#endif // WIN32 #endif // WIN32
if (!_got_temp_directory) { if (temp_directory.empty()) {
// Fallback case. // Fallback case.
_temp_directory = ExecutionEnvironment::get_cwd(); temp_directory = ExecutionEnvironment::get_cwd();
_got_temp_directory = true; }
Filename *newdir = new Filename(temp_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_temp_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else.
assert(_temp_directory != NULL);
delete newdir;
} }
} }
return _temp_directory; return (*_temp_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -550,37 +558,42 @@ get_temp_directory() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_app_directory() { get_app_directory() {
if (!_got_app_directory) { if (AtomicAdjust::get_ptr(_app_directory) == NULL) {
Filename app_directory;
#if defined(IS_OSX) #if defined(IS_OSX)
_app_directory = get_osx_app_directory(); app_directory = get_osx_app_directory();
_got_app_directory = !_app_directory.empty();
#endif // WIN32 #endif // WIN32
if (!_got_app_directory) { if (app_directory.empty()) {
// Fallback case. // Fallback case.
Filename binary_name = ExecutionEnvironment::get_binary_name(); Filename binary_name = ExecutionEnvironment::get_binary_name();
if (!binary_name.empty()) { if (!binary_name.empty()) {
_app_directory = binary_name.get_dirname(); app_directory = binary_name.get_dirname();
_got_app_directory = !_app_directory.empty();
} }
} }
if (!_got_app_directory) { if (app_directory.empty()) {
// Another fallback. // Another fallback.
Filename dtool_name = ExecutionEnvironment::get_dtool_name(); Filename dtool_name = ExecutionEnvironment::get_dtool_name();
if (!dtool_name.empty()) { if (!dtool_name.empty()) {
_app_directory = dtool_name.get_dirname(); app_directory = dtool_name.get_dirname();
_got_app_directory = !_app_directory.empty();
} }
} }
if (!_got_app_directory) { if (app_directory.empty()) {
// The final fallback. // The final fallback.
_app_directory = ExecutionEnvironment::get_cwd(); app_directory = ExecutionEnvironment::get_cwd();
_got_app_directory = true; }
Filename *newdir = new Filename(app_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_app_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else.
assert(_app_directory != NULL);
delete newdir;
} }
} }
return _app_directory; return (*_app_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -593,38 +606,44 @@ get_app_directory() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_user_appdata_directory() { get_user_appdata_directory() {
if (!_got_user_appdata_directory) { if (AtomicAdjust::get_ptr(_user_appdata_directory) == NULL) {
Filename user_appdata_directory;
#ifdef WIN32 #ifdef WIN32
char buffer[MAX_PATH]; char buffer[MAX_PATH];
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_APPDATA, true)) { if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_APPDATA, true)) {
_user_appdata_directory = from_os_specific(buffer); Filename dirname = from_os_specific(buffer);
if (_user_appdata_directory.is_directory()) { if (dirname.is_directory()) {
if (_user_appdata_directory.make_canonical()) { if (dirname.make_canonical()) {
_got_user_appdata_directory = true; user_appdata_directory = dirname;
} }
} }
} }
#elif defined(IS_OSX) #elif defined(IS_OSX)
_user_appdata_directory = get_osx_user_appdata_directory(); user_appdata_directory = get_osx_user_appdata_directory();
_got_user_appdata_directory = true;
#else #else
// Posix case. // Posix case.
_user_appdata_directory = get_home_directory(); user_appdata_directory = get_home_directory();
_got_user_appdata_directory = true;
#endif // WIN32 #endif // WIN32
if (!_got_user_appdata_directory) { if (user_appdata_directory.empty()) {
// Fallback case. // Fallback case.
_user_appdata_directory = ExecutionEnvironment::get_cwd(); user_appdata_directory = ExecutionEnvironment::get_cwd();
_got_user_appdata_directory = true; }
Filename *newdir = new Filename(user_appdata_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_user_appdata_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else.
assert(_user_appdata_directory != NULL);
delete newdir;
} }
} }
return _user_appdata_directory; return (*_user_appdata_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -636,37 +655,43 @@ get_user_appdata_directory() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_common_appdata_directory() { get_common_appdata_directory() {
if (!_got_common_appdata_directory) { if (AtomicAdjust::get_ptr(_common_appdata_directory) == NULL) {
Filename common_appdata_directory;
#ifdef WIN32 #ifdef WIN32
char buffer[MAX_PATH]; char buffer[MAX_PATH];
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_COMMON_APPDATA, true)) { if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_COMMON_APPDATA, true)) {
_common_appdata_directory = from_os_specific(buffer); Filename dirname = from_os_specific(buffer);
if (_common_appdata_directory.is_directory()) { if (dirname.is_directory()) {
if (_common_appdata_directory.make_canonical()) { if (dirname.make_canonical()) {
_got_common_appdata_directory = true; common_appdata_directory = dirname;
} }
} }
} }
#elif defined(IS_OSX) #elif defined(IS_OSX)
_common_appdata_directory = get_osx_common_appdata_directory(); common_appdata_directory = get_osx_common_appdata_directory();
_got_common_appdata_directory = true;
#else #else
// Posix case. // Posix case.
_common_appdata_directory = "/var"; common_appdata_directory = "/var";
_got_common_appdata_directory = true;
#endif // WIN32 #endif // WIN32
if (!_got_common_appdata_directory) { if (common_appdata_directory.empty()) {
// Fallback case. // Fallback case.
_common_appdata_directory = ExecutionEnvironment::get_cwd(); common_appdata_directory = ExecutionEnvironment::get_cwd();
_got_common_appdata_directory = true; }
Filename *newdir = new Filename(common_appdata_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_common_appdata_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else.
assert(_common_appdata_directory != NULL);
delete newdir;
} }
} }
return _common_appdata_directory; return (*_common_appdata_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -232,16 +232,11 @@ protected:
int _flags; int _flags;
static bool _got_home_directory; static Filename *_home_directory;
static Filename _home_directory; static Filename *_temp_directory;
static bool _got_temp_directory; static Filename *_app_directory;
static Filename _temp_directory; static Filename *_user_appdata_directory;
static bool _got_app_directory; static Filename *_common_appdata_directory;
static Filename _app_directory;
static bool _got_user_appdata_directory;
static Filename _user_appdata_directory;
static bool _got_common_appdata_directory;
static Filename _common_appdata_directory;
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {