diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2018-05-30 09:00:20 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2018-05-30 12:57:37 +0200 |
commit | dfda2730a11e165f081dacbb4b5c30da3db07070 (patch) | |
tree | 017915658cf18ac74f4e1595d3a9a62b8f00912c | |
parent | 8b43f58891d4b422a8934050d839b0c2c1e3a18a (diff) |
protect one-time creation in ScGlobal::Get(Case)Collator() by a mutex
Otherwise there is a race condition when calc uses threading, and lp#390983-2
sometimes crashes.
Change-Id: I390928c02b8e7d74bebef2dcc98a5c21cb3a8197
Reviewed-on: https://gerrit.libreoffice.org/54795
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r-- | sc/source/core/data/global.cxx | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx index 9e4ce14e3ddf..4ab08a7bc1bd 100644 --- a/sc/source/core/data/global.cxx +++ b/sc/source/core/data/global.cxx @@ -125,6 +125,33 @@ SfxViewShell* pScActiveViewShell = nullptr; //FIXME: Make this a member sal_uInt16 nScClickMouseModifier = 0; //FIXME: This too sal_uInt16 nScFillModeMouseModifier = 0; //FIXME: And this +// Thread-safe singleton creation. Ideally rtl_Instance should be used, but that one doesn't +// allow accessing the pointer (so ScGlobal::Clear() cannot free the objects). So this function +// is basically rtl_Instance::create() that uses a given pointer. +template< typename Type, typename Function = std::function< Type*() >, + typename Guard = osl::MutexGuard, typename GuardCtor = osl::GetGlobalMutex > +static inline +Type* doubleCheckedInit( Type* pointer, Function function, GuardCtor guardCtor = osl::GetGlobalMutex()) +{ + Type* p = pointer; + if (!p) + { + Guard guard(guardCtor()); + p = pointer; + if (!p) + { + p = function(); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pointer = p; + } + } + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return p; +} + // Static functions bool ScGlobal::HasAttrChanged( const SfxItemSet& rNewAttrs, @@ -996,21 +1023,23 @@ CalendarWrapper* ScGlobal::GetCalendar() } CollatorWrapper* ScGlobal::GetCollator() { - if ( !pCollator ) - { - pCollator = new CollatorWrapper( ::comphelper::getProcessComponentContext() ); - pCollator->loadDefaultCollator( *GetLocale(), SC_COLLATOR_IGNORES ); - } - return pCollator; + return doubleCheckedInit( pCollator, + []() + { + CollatorWrapper* p = new CollatorWrapper( ::comphelper::getProcessComponentContext() ); + p->loadDefaultCollator( *GetLocale(), SC_COLLATOR_IGNORES ); + return p; + }); } CollatorWrapper* ScGlobal::GetCaseCollator() { - if ( !pCaseCollator ) - { - pCaseCollator = new CollatorWrapper( ::comphelper::getProcessComponentContext() ); - pCaseCollator->loadDefaultCollator( *GetLocale(), 0 ); - } - return pCaseCollator; + return doubleCheckedInit( pCaseCollator, + []() + { + CollatorWrapper* p = new CollatorWrapper( ::comphelper::getProcessComponentContext() ); + p->loadDefaultCollator( *GetLocale(), 0 ); + return p; + }); } ::utl::TransliterationWrapper* ScGlobal::GetCaseTransliteration() { |