X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1224b8a3865f070ff541c0f1f3b889380abd087f..326b62161d387b4181b797a76652796f730172fb:/include/wx/string.h diff --git a/include/wx/string.h b/include/wx/string.h index b369223e71..b66afd79ae 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -594,26 +594,38 @@ private: unsigned lastUsed; }; - // notice that we must use an accessor function and not a static variable - // because when the TLS variables support is implemented in the library (and - // not by the compiler), the global s_cache variable could be not yet - // initialized when a ctor of another global object is executed and if that - // ctor uses any wxString methods, bad things happen - static Cache& GetCache() +#ifndef wxHAS_COMPILER_TLS + // we must use an accessor function and not a static variable when the TLS + // variables support is implemented in the library (and not by the compiler) + // because the global s_cache variable could be not yet initialized when a + // ctor of another global object is executed and if that ctor uses any + // wxString methods, bad things happen + // + // however notice that this approach does not work when compiler TLS is used, + // at least not with g++ 4.1.2 under amd64 as it apparently compiles code + // using this accessor incorrectly when optimizations are enabled (-O2 is + // enough) -- luckily we don't need it then neither as static __thread + // variables are initialized by 0 anyhow then and so we can use the variable + // directly + WXEXPORT static Cache& GetCache() { static wxTLS_TYPE(Cache) s_cache; return wxTLS_VALUE(s_cache); } - - static Cache::Element *GetCacheBegin() { return GetCache().cached; } - static Cache::Element *GetCacheEnd() { return GetCacheBegin() + Cache::SIZE; } - static unsigned& LastUsedCacheElement() { return GetCache().lastUsed; } - + // this helper struct is used to ensure that GetCache() is called during // static initialization time, i.e. before any threads creation, as otherwise // the static s_cache construction inside GetCache() wouldn't be MT-safe friend struct wxStrCacheInitializer; +#else // wxHAS_COMPILER_TLS + static wxTLS_TYPE(Cache) ms_cache; + static Cache& GetCache() { return wxTLS_VALUE(ms_cache); } +#endif // !wxHAS_COMPILER_TLS/wxHAS_COMPILER_TLS + + static Cache::Element *GetCacheBegin() { return GetCache().cached; } + static Cache::Element *GetCacheEnd() { return GetCacheBegin() + Cache::SIZE; } + static unsigned& LastUsedCacheElement() { return GetCache().lastUsed; } // this is used in debug builds only to provide a convenient function, // callable from a debugger, to show the cache contents @@ -659,7 +671,15 @@ private: // profiling seems to show a small but consistent gain if we use this // simple loop instead of starting from the last used element (there are // a lot of misses in this function...) - for ( Cache::Element *c = GetCacheBegin(); c != GetCacheEnd(); c++ ) + Cache::Element * const cacheBegin = GetCacheBegin(); +#ifndef wxHAS_COMPILER_TLS + // during destruction tls calls may return NULL, in this case return NULL + // immediately without accessing anything else + if ( cacheBegin == NULL ) + return NULL; +#endif + Cache::Element * const cacheEnd = GetCacheEnd(); + for ( Cache::Element *c = cacheBegin; c != cacheEnd; c++ ) { if ( c->str == this ) return c; @@ -1438,12 +1458,7 @@ public: // truncate the string to given length wxString& Truncate(size_t uiLen); // empty string contents - void Empty() - { - Truncate(0); - - wxASSERT_MSG( empty(), _T("string not empty after call to Empty()?") ); - } + void Empty() { clear(); } // empty the string and free memory void Clear() { clear(); }