From ad8ae78878ee48f0c4eb2deb0995ab07a1d23f72 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sun, 31 Aug 2008 14:57:53 +0000
Subject: [PATCH] call GetCache() from a global object ctor to ensure that it
 is done before any threads are created

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55393 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 include/wx/string.h   | 12 +++++++-----
 src/common/string.cpp | 17 +++++++++++++++++
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/include/wx/string.h b/include/wx/string.h
index 9cbcc49a28..d8aebef9ac 100644
--- a/include/wx/string.h
+++ b/include/wx/string.h
@@ -599,11 +599,6 @@ private:
   // 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
-  //
-  // also note that for the same reason this function _is_ MT-safe: we know
-  // it's going to be called during the program startup (currently during
-  // globals initialization but even if they ever stop using wxString, it would
-  // still be called by wxInitialize()), i.e. before any threads are created
   static Cache& GetCache()
   {
       static wxTLS_TYPE(Cache) s_cache;
@@ -615,6 +610,13 @@ private:
   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;
+
+  // this is used in debug builds only to provide a convenient function,
+  // callable from a debugger, to show the cache contents
   friend struct wxStrCacheDumper;
 
   // uncomment this to have access to some profiling statistics on program
diff --git a/src/common/string.cpp b/src/common/string.cpp
index 85b3090533..827099f0a6 100644
--- a/src/common/string.cpp
+++ b/src/common/string.cpp
@@ -60,10 +60,25 @@ const size_t wxString::npos = (size_t) -1;
 
 #if wxUSE_STRING_POS_CACHE
 
+struct wxStrCacheInitializer
+{
+    wxStrCacheInitializer()
+    {
+        // calling this function triggers s_cache initialization in it, and
+        // from now on it becomes safe to call from multiple threads
+        wxString::GetCache();
+    }
+};
+
+static wxStrCacheInitializer gs_stringCacheInit;
+
 // 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__
 
+namespace
+{
+
 struct wxStrCacheDumper
 {
     static void ShowAll()
@@ -85,6 +100,8 @@ struct wxStrCacheDumper
     }
 };
 
+} // anonymous namespace
+
 void wxDumpStrCache() { wxStrCacheDumper::ShowAll(); }
 
 #endif // __WXDEBUG__
-- 
2.47.2