From e810df36b3d5e73e53e2d536802df0174c571bb2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 6 Sep 2008 22:12:04 +0000 Subject: [PATCH] access TLS cache variable directly and not via a helper function when using compiler with native TLS support to work around an apparent bug in g++ git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55501 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/string.h | 30 +++++++++++++++++++++--------- src/common/string.cpp | 8 ++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/include/wx/string.h b/include/wx/string.h index b369223e71..98d5c6da71 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -594,11 +594,19 @@ 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 +#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 static Cache& GetCache() { static wxTLS_TYPE(Cache) s_cache; @@ -606,14 +614,18 @@ private: 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 diff --git a/src/common/string.cpp b/src/common/string.cpp index 82acf49d86..13804f2211 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -60,6 +60,12 @@ const size_t wxString::npos = (size_t) -1; #if wxUSE_STRING_POS_CACHE +#ifdef wxHAS_COMPILER_TLS + +wxTLS_TYPE(wxString::Cache) wxString::ms_cache; + +#else // !wxHAS_COMPILER_TLS + struct wxStrCacheInitializer { wxStrCacheInitializer() @@ -72,6 +78,8 @@ struct wxStrCacheInitializer static wxStrCacheInitializer gs_stringCacheInit; +#endif // wxHAS_COMPILER_TLS/!wxHAS_COMPILER_TLS + // gdb seems to be unable to display thread-local variables correctly, at least // not my 6.4.98 version under amd64, so provide this debugging helper to do it #ifdef __WXDEBUG__ -- 2.45.2