Make _() and friends safe to call from any thread.

The GetUntranslatedString() hack keeps a global copy of all strings, so
that it can return a const reference as wxGetTranslation() return value.
A global wxHashSet instance shared by all threads won't do, even guarded
with a critical section, because it may internally copy values on any
insert and thus invalidate pointers that may still be used on another
thread.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74833 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2013-09-18 16:03:20 +00:00
parent 92c0fc34c1
commit d2740de55e
4 changed files with 29 additions and 12 deletions

View File

@@ -568,6 +568,7 @@ All:
- Fix build with wxUSE_FFILE==0 (jroemmler). - Fix build with wxUSE_FFILE==0 (jroemmler).
- Add wxDEPRECATED_MSG() and use it in a few places. - Add wxDEPRECATED_MSG() and use it in a few places.
- Return the old file descriptor/pointer from wx(F)File::Detach() (troelsk). - Return the old file descriptor/pointer from wx(F)File::Detach() (troelsk).
- _() and wxGetTranslation() are now thread-safe.
All (GUI): All (GUI):

View File

@@ -14,6 +14,13 @@
class WXDLLIMPEXP_FWD_BASE wxLog; class WXDLLIMPEXP_FWD_BASE wxLog;
#if wxUSE_INTL
#include "wx/hashset.h"
WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual,
wxLocaleUntranslatedStrings);
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxThreadSpecificInfo: contains all thread-specific information used by wx // wxThreadSpecificInfo: contains all thread-specific information used by wx
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -40,6 +47,11 @@ public:
// logging // logging
bool loggingDisabled; bool loggingDisabled;
#if wxUSE_INTL
// Storage for wxTranslations::GetUntranslatedString()
wxLocaleUntranslatedStrings untranslatedStrings;
#endif
private: private:
wxThreadSpecificInfo() : logger(NULL), loggingDisabled(false) {} wxThreadSpecificInfo() : logger(NULL), loggingDisabled(false) {}
}; };

View File

@@ -234,6 +234,8 @@ public:
error message is generated the first time a string is not found; use error message is generated the first time a string is not found; use
wxLogNull to suppress it). wxLogNull to suppress it).
This function is thread-safe.
@remarks Domains are searched in the last to first order, i.e. catalogs @remarks Domains are searched in the last to first order, i.e. catalogs
added later override those added before. added later override those added before.
*/ */
@@ -264,6 +266,8 @@ public:
See GNU gettext manual for additional information on plural forms handling. See GNU gettext manual for additional information on plural forms handling.
This method is called by the wxGetTranslation() function and _() macro. This method is called by the wxGetTranslation() function and _() macro.
This function is thread-safe.
@remarks Domains are searched in the last to first order, i.e. catalogs @remarks Domains are searched in the last to first order, i.e. catalogs
added later override those added before. added later override those added before.
*/ */
@@ -515,6 +519,8 @@ public:
This function calls wxTranslations::GetString(). This function calls wxTranslations::GetString().
This function is thread-safe.
@note This function is not suitable for literal strings in Unicode builds @note This function is not suitable for literal strings in Unicode builds
since the literal strings must be enclosed in wxT() macro which makes since the literal strings must be enclosed in wxT() macro which makes
them unrecognised by @c xgettext, and so they are not extracted to them unrecognised by @c xgettext, and so they are not extracted to
@@ -546,7 +552,9 @@ const wxString& wxGetTranslation(const wxString& string,
<http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms> <http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>
For a shorter alternative see the wxPLURAL() macro. For a shorter alternative see the wxPLURAL() macro.
This function calls wxLocale::GetString(). This function calls wxTranslation::GetString().
This function is thread-safe.
@header{wx/intl.h} @header{wx/intl.h}
*/ */
@@ -562,6 +570,8 @@ const wxString& wxGetTranslation(const wxString& string,
also returns the translation of the string for the current locale during also returns the translation of the string for the current locale during
execution. execution.
This macro is thread-safe.
@header{wx/intl.h} @header{wx/intl.h}
*/ */
const wxString& _(const wxString& string); const wxString& _(const wxString& string);

View File

@@ -47,7 +47,7 @@
#include "wx/tokenzr.h" #include "wx/tokenzr.h"
#include "wx/fontmap.h" #include "wx/fontmap.h"
#include "wx/stdpaths.h" #include "wx/stdpaths.h"
#include "wx/hashset.h" #include "wx/private/threadinfo.h"
#ifdef __WINDOWS__ #ifdef __WINDOWS__
#include "wx/dynlib.h" #include "wx/dynlib.h"
@@ -1605,20 +1605,14 @@ wxString wxTranslations::GetBestTranslation(const wxString& domain,
} }
namespace
{
WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual,
wxLocaleUntranslatedStrings);
}
/* static */ /* static */
const wxString& wxTranslations::GetUntranslatedString(const wxString& str) const wxString& wxTranslations::GetUntranslatedString(const wxString& str)
{ {
static wxLocaleUntranslatedStrings s_strings; wxLocaleUntranslatedStrings& strings = wxThreadInfo.untranslatedStrings;
wxLocaleUntranslatedStrings::iterator i = s_strings.find(str); wxLocaleUntranslatedStrings::iterator i = strings.find(str);
if ( i == s_strings.end() ) if ( i == strings.end() )
return *s_strings.insert(str).first; return *strings.insert(str).first;
return *i; return *i;
} }