summaryrefslogtreecommitdiff
path: root/i18nlangtag/source
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2021-11-10 17:02:52 +0100
committerStephan Bergmann <sbergman@redhat.com>2021-11-10 18:15:22 +0100
commit6334f7dc43f69ada4341d5f0dd1a0f1e13113b4f (patch)
treea2bd5a414876db8fcc70dbe03d1a01d455091985 /i18nlangtag/source
parent0ac45af39c534ce17a4a76a370add4ffa4fa92f9 (diff)
initialization-order-fiasco, again
...after b5758cb2729236d9eaf52bd25b1b113a3ff06b4e "rtl::Static to thread-safe static" (which this partially reverts again), like 71d0c43fb4cf535239cb41baf7b6e03de765ce7a "initialization-order-fiasco" in the past Change-Id: Ie3f352a63ee3939b1727faf6cf11b2768173437c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124998 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'i18nlangtag/source')
-rw-r--r--i18nlangtag/source/languagetag/languagetag.cxx107
1 files changed, 54 insertions, 53 deletions
diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 83d730f5fc5f..6f6a766e861f 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -18,6 +18,7 @@
#include <sal/log.hxx>
#include <osl/file.hxx>
#include <osl/mutex.hxx>
+#include <rtl/instance.hxx>
#include <rtl/locale.h>
#include <tools/long.hxx>
#include <algorithm>
@@ -49,32 +50,42 @@ struct myLtError
};
// "static" to be returned as const reference to an empty locale.
-const lang::Locale theEmptyLocale;
+struct theEmptyLocale : public rtl::Static< lang::Locale, theEmptyLocale > {};
+}
typedef std::unordered_set< OUString > KnownTagSet;
+namespace {
+struct theKnowns : public rtl::Static< KnownTagSet, theKnowns > {};
+struct theMutex : public rtl::Static< osl::Mutex, theMutex > {};
+}
-const KnownTagSet & getKnowns()
+static const KnownTagSet & getKnowns()
{
- static KnownTagSet theKnowns = []()
+ KnownTagSet & rKnowns = theKnowns::get();
+ if (rKnowns.empty())
{
- KnownTagSet ret;
- ::std::vector< MsLangId::LanguagetagMapping > aDefined( MsLangId::getDefinedLanguagetags());
- for (auto const& elemDefined : aDefined)
+ osl::MutexGuard aGuard( theMutex::get());
+ if (rKnowns.empty())
{
- // Do not use the BCP47 string here to initialize the
- // LanguageTag because then canonicalize() would call this
- // getKnowns() again...
- ::std::vector< OUString > aFallbacks( LanguageTag( elemDefined.mnLang).getFallbackStrings( true));
- for (auto const& fallback : aFallbacks)
+ ::std::vector< MsLangId::LanguagetagMapping > aDefined( MsLangId::getDefinedLanguagetags());
+ for (auto const& elemDefined : aDefined)
{
- ret.insert(fallback);
+ // Do not use the BCP47 string here to initialize the
+ // LanguageTag because then canonicalize() would call this
+ // getKnowns() again...
+ ::std::vector< OUString > aFallbacks( LanguageTag( elemDefined.mnLang).getFallbackStrings( true));
+ for (auto const& fallback : aFallbacks)
+ {
+ rKnowns.insert(fallback);
+ }
}
}
- return ret;
- }();
- return theKnowns;
+ }
+ return rKnowns;
}
+
+namespace {
struct compareIgnoreAsciiCaseLess
{
bool operator()( const OUString& r1, std::u16string_view r2 ) const
@@ -84,23 +95,17 @@ struct compareIgnoreAsciiCaseLess
};
typedef ::std::map< OUString, LanguageTag::ImplPtr, compareIgnoreAsciiCaseLess > MapBcp47;
typedef ::std::map< LanguageType, LanguageTag::ImplPtr > MapLangID;
-MapBcp47 theMapBcp47;
-MapLangID theMapLangID;
-LanguageTag::ImplPtr theDontKnow;
-LanguageTag::ImplPtr theSystemLocale;
-osl::Mutex& theMutex()
-{
- static osl::Mutex SINGLETON;
- return SINGLETON;
-}
-
+struct theMapBcp47 : public rtl::Static< MapBcp47, theMapBcp47 > {};
+struct theMapLangID : public rtl::Static< MapLangID, theMapLangID > {};
+struct theDontKnow : public rtl::Static< LanguageTag::ImplPtr, theDontKnow > {};
+struct theSystemLocale : public rtl::Static< LanguageTag::ImplPtr, theSystemLocale > {};
}
static LanguageType getNextOnTheFlyLanguage()
{
static LanguageType nOnTheFlyLanguage(0);
- osl::MutexGuard aGuard(theMutex());
+ osl::MutexGuard aGuard( theMutex::get());
if (!nOnTheFlyLanguage)
nOnTheFlyLanguage = MsLangId::makeLangID( LANGUAGE_ON_THE_FLY_SUB_START, LANGUAGE_ON_THE_FLY_START);
else
@@ -166,11 +171,7 @@ private:
static void teardown();
};
-LiblangtagDataRef& theDataRef()
-{
- static LiblangtagDataRef SINGLETON;
- return SINGLETON;
-}
+struct theDataRef : public rtl::Static< LiblangtagDataRef, theDataRef > {};
}
LiblangtagDataRef::LiblangtagDataRef()
@@ -428,7 +429,7 @@ LanguageTagImpl::LanguageTagImpl( const LanguageTagImpl & rLanguageTagImpl )
mbCachedGlibcString( rLanguageTagImpl.mbCachedGlibcString)
{
if (mpImplLangtag)
- theDataRef().init();
+ theDataRef::get().init();
}
@@ -464,7 +465,7 @@ LanguageTagImpl& LanguageTagImpl::operator=( const LanguageTagImpl & rLanguageTa
mbCachedVariants = rLanguageTagImpl.mbCachedVariants;
mbCachedGlibcString = rLanguageTagImpl.mbCachedGlibcString;
if (mpImplLangtag && !oldTag)
- theDataRef().init();
+ theDataRef::get().init();
return *this;
}
@@ -595,9 +596,9 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
return pImpl;
}
- osl::MutexGuard aGuard( theMutex());
+ osl::MutexGuard aGuard( theMutex::get());
- MapBcp47& rMapBcp47 = theMapBcp47;
+ MapBcp47& rMapBcp47 = theMapBcp47::get();
MapBcp47::const_iterator it( rMapBcp47.find( maBcp47));
bool bOtherImpl = false;
if (it != rMapBcp47.end())
@@ -633,7 +634,7 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
// different, otherwise we would end up with ambiguous assignments
// of different language tags, for example for the same primary
// LangID with "no", "nb" and "nn".
- const MapLangID& rMapLangID = theMapLangID;
+ const MapLangID& rMapLangID = theMapLangID::get();
MapLangID::const_iterator itID( rMapLangID.find( nRegisterID));
if (itID != rMapLangID.end())
{
@@ -666,7 +667,7 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
}
::std::pair< MapLangID::const_iterator, bool > res(
- theMapLangID.insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
+ theMapLangID::get().insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
if (res.second)
{
SAL_INFO( "i18nlangtag", "LanguageTag::registerOnTheFly: cross-inserted 0x"
@@ -685,7 +686,7 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
LanguageTag::ScriptType LanguageTag::getOnTheFlyScriptType( LanguageType nRegisterID )
{
- const MapLangID& rMapLangID = theMapLangID;
+ const MapLangID& rMapLangID = theMapLangID::get();
MapLangID::const_iterator itID( rMapLangID.find( nRegisterID));
if (itID != rMapLangID.end())
return (*itID).second->getScriptType();
@@ -708,7 +709,7 @@ void LanguageTag::setConfiguredSystemLanguage( LanguageType nLang )
MsLangId::LanguageTagAccess::setConfiguredSystemLanguage( nLang);
// Reset system locale to none and let registerImpl() do the rest to
// initialize a new one.
- theSystemLocale.reset();
+ theSystemLocale::get().reset();
LanguageTag aLanguageTag( LANGUAGE_SYSTEM);
aLanguageTag.registerImpl();
}
@@ -748,7 +749,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
// and take the system locale shortcut if possible.
if (mbSystemLocale)
{
- pImpl = theSystemLocale;
+ pImpl = theSystemLocale::get();
if (pImpl)
{
#if OSL_DEBUG_LEVEL > 0
@@ -773,7 +774,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
// Heavy usage of LANGUAGE_DONTKNOW, make it an own Impl for all the
// conversion attempts. At the same time provide a central breakpoint
// to inspect such places.
- LanguageTag::ImplPtr& rDontKnow = theDontKnow;
+ LanguageTag::ImplPtr& rDontKnow = theDontKnow::get();
if (!rDontKnow)
rDontKnow = std::make_shared<LanguageTagImpl>( *this);
pImpl = rDontKnow;
@@ -787,7 +788,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
else
{
// A great share are calls for a system equal locale.
- pImpl = theSystemLocale;
+ pImpl = theSystemLocale::get();
if (pImpl && pImpl->mnLangID == mnLangID)
{
#if OSL_DEBUG_LEVEL > 0
@@ -818,7 +819,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
if (mbInitializedBcp47)
{
// A great share are calls for a system equal locale.
- pImpl = theSystemLocale;
+ pImpl = theSystemLocale::get();
if (pImpl && pImpl->maBcp47 == maBcp47)
{
#if OSL_DEBUG_LEVEL > 0
@@ -836,7 +837,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: " << nCallsNonSystem << " non-system calls");
#endif
- osl::MutexGuard aGuard( theMutex());
+ osl::MutexGuard aGuard( theMutex::get());
#if OSL_DEBUG_LEVEL > 0
static tools::Long nRunning = 0;
@@ -851,7 +852,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
// Prefer LangID map as find+insert needs less comparison work.
if (mbInitializedLangID)
{
- MapLangID& rMap = theMapLangID;
+ MapLangID& rMap = theMapLangID::get();
MapLangID::const_iterator it( rMap.find( mnLangID));
if (it != rMap.end())
{
@@ -873,7 +874,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
if (!pImpl->mbInitializedBcp47)
pImpl->convertLocaleToBcp47();
::std::pair< MapBcp47::const_iterator, bool > res(
- theMapBcp47.insert( ::std::make_pair( pImpl->maBcp47, pImpl)));
+ theMapBcp47::get().insert( ::std::make_pair( pImpl->maBcp47, pImpl)));
if (res.second)
{
SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: cross-inserted '" << pImpl->maBcp47 << "' for 0x" << ::std::hex << mnLangID);
@@ -894,7 +895,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
}
else if (!maBcp47.isEmpty())
{
- MapBcp47& rMap = theMapBcp47;
+ MapBcp47& rMap = theMapBcp47::get();
MapBcp47::const_iterator it( rMap.find( maBcp47));
if (it != rMap.end())
{
@@ -956,7 +957,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
if (bInsert)
{
::std::pair< MapLangID::const_iterator, bool > res(
- theMapLangID.insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
+ theMapLangID::get().insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
if (res.second)
{
SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: cross-inserted 0x"
@@ -988,7 +989,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
// above, so add it.
if (mbSystemLocale && mbInitializedLangID)
{
- theSystemLocale = pImpl;
+ theSystemLocale::get() = pImpl;
SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: added system locale 0x"
<< ::std::hex << pImpl->mnLangID << " '" << pImpl->maBcp47 << "'");
}
@@ -1210,7 +1211,7 @@ bool LanguageTagImpl::canonicalize()
if (!mpImplLangtag)
{
- theDataRef().init();
+ theDataRef::get().init();
mpImplLangtag = lt_tag_new();
}
@@ -1526,7 +1527,7 @@ void LanguageTag::convertFromRtlLocale()
* string. */
#if 0
myLtError aError;
- theDataRef().init();
+ theDataRef::get().init();
mpImplLangtag = lt_tag_convert_from_locale( aStr.getStr(), &aError.p);
maBcp47 = OStringToOUString( lt_tag_get_string( mpImplLangtag), RTL_TEXTENCODING_UTF8);
mbInitializedBcp47 = true;
@@ -1698,7 +1699,7 @@ OUString LanguageTagImpl::getVariantsFromLangtag()
const css::lang::Locale & LanguageTag::getLocale( bool bResolveSystem ) const
{
if (!bResolveSystem && mbSystemLocale)
- return theEmptyLocale;
+ return theEmptyLocale::get();
if (!mbInitializedLocale)
syncVarsFromImpl();
if (!mbInitializedLocale)
@@ -2831,7 +2832,7 @@ bool LanguageTag::isValidBcp47( const OUString& rString, OUString* o_pCanonicali
lt_tag_t* mpLangtag;
guard()
{
- theDataRef().init();
+ theDataRef::get().init();
mpLangtag = lt_tag_new();
}
~guard()