summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2018-05-30 09:00:20 +0200
committerLuboš Luňák <l.lunak@collabora.com>2018-05-30 12:57:37 +0200
commitdfda2730a11e165f081dacbb4b5c30da3db07070 (patch)
tree017915658cf18ac74f4e1595d3a9a62b8f00912c /sc
parent8b43f58891d4b422a8934050d839b0c2c1e3a18a (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>
Diffstat (limited to 'sc')
-rw-r--r--sc/source/core/data/global.cxx53
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()
{