summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2014-08-19 23:29:32 +0200
committerMichael Stahl <mstahl@redhat.com>2014-08-20 16:40:16 +0200
commit14eb485c5c62a4f745b24a3798f313623f283e55 (patch)
treefab271ff05b8bb802a66b714b32171cf6f04099e
parent1e28d7901dbebf77f75e5770d11a49fef036976c (diff)
i#107771: sw: implement thread-safe instance caching for SwXReferenceMark
Change-Id: I4f3b6789dde053ca913e12233b20d45dfe50c7ec
-rw-r--r--sw/inc/fmtrfmrk.hxx16
-rw-r--r--sw/inc/unocoll.hxx1
-rw-r--r--sw/source/core/inc/unorefmark.hxx11
-rw-r--r--sw/source/core/txtnode/atrref.cxx9
-rw-r--r--sw/source/core/unocore/unocoll.cxx19
-rw-r--r--sw/source/core/unocore/unocrsrhelper.cxx4
-rw-r--r--sw/source/core/unocore/unoportenum.cxx2
-rw-r--r--sw/source/core/unocore/unorefmk.cxx35
8 files changed, 59 insertions, 38 deletions
diff --git a/sw/inc/fmtrfmrk.hxx b/sw/inc/fmtrfmrk.hxx
index d8e807d18381..4825699a6fae 100644
--- a/sw/inc/fmtrfmrk.hxx
+++ b/sw/inc/fmtrfmrk.hxx
@@ -20,10 +20,15 @@
#define INCLUDED_SW_INC_FMTRFMRK_HXX
#include <rtl/ustring.hxx>
+#include <cppuhelper/weakref.hxx>
#include <svl/poolitem.hxx>
#include <calbck.hxx>
+namespace com { namespace sun { namespace star {
+ namespace text { class XTextContent; }
+} } }
+
class SwTxtRefMark;
// ATT_REFMARK
@@ -39,6 +44,8 @@ class SwFmtRefMark
SwFmtRefMark& operator=(const SwFmtRefMark& rRefMark);
OUString aRefName;
+ css::uno::WeakReference<css::text::XTextContent> m_wXReferenceMark;
+
public:
SwFmtRefMark( const OUString& rTxt );
SwFmtRefMark( const SwFmtRefMark& rRefMark );
@@ -48,6 +55,10 @@ public:
virtual bool operator==( const SfxPoolItem& ) const SAL_OVERRIDE;
virtual SfxPoolItem* Clone( SfxItemPool* pPool = 0 ) const SAL_OVERRIDE;
+ // SwClient
+ virtual void Modify(SfxPoolItem const* pOld, SfxPoolItem const* pNew)
+ SAL_OVERRIDE;
+
void InvalidateRefMark();
const SwTxtRefMark *GetTxtRefMark() const { return pTxtAttr; }
@@ -55,6 +66,11 @@ public:
inline OUString &GetRefName() { return aRefName; }
inline const OUString &GetRefName() const { return aRefName; }
+
+ css::uno::WeakReference<css::text::XTextContent> const& GetXRefMark() const
+ { return m_wXReferenceMark; }
+ void SetXRefMark(css::uno::Reference<css::text::XTextContent> const& xMark)
+ { m_wXReferenceMark = xMark; }
};
#endif
diff --git a/sw/inc/unocoll.hxx b/sw/inc/unocoll.hxx
index eb55c8116f84..d5c97bb44d21 100644
--- a/sw/inc/unocoll.hxx
+++ b/sw/inc/unocoll.hxx
@@ -521,7 +521,6 @@ public:
virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw( ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw( ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
- static SwXReferenceMark* GetObject( SwDoc* pDoc, const SwFmtRefMark* pMark );
};
#endif
diff --git a/sw/source/core/inc/unorefmark.hxx b/sw/source/core/inc/unorefmark.hxx
index 78dac4b0207c..73d8d410d97d 100644
--- a/sw/source/core/inc/unorefmark.hxx
+++ b/sw/source/core/inc/unorefmark.hxx
@@ -53,15 +53,12 @@ private:
virtual ~SwXReferenceMark();
-public:
-
SwXReferenceMark(SwDoc *const pDoc, SwFmtRefMark *const pMark);
- static SwXReferenceMark *
- CreateXReferenceMark(SwDoc & rDoc, SwFmtRefMark & rMarkFmt);
- /// may return 0
- static SwXReferenceMark *
- GetReferenceMark(SwModify const& rUnoCB, SwFmtRefMark const& rMarkFmt);
+public:
+
+ static css::uno::Reference<css::text::XTextContent>
+ CreateXReferenceMark(SwDoc & rDoc, SwFmtRefMark * pMarkFmt);
static const ::com::sun::star::uno::Sequence< sal_Int8 >& getUnoTunnelId();
diff --git a/sw/source/core/txtnode/atrref.cxx b/sw/source/core/txtnode/atrref.cxx
index 1b9fe63d0413..35f338b30e48 100644
--- a/sw/source/core/txtnode/atrref.cxx
+++ b/sw/source/core/txtnode/atrref.cxx
@@ -55,6 +55,15 @@ SfxPoolItem* SwFmtRefMark::Clone( SfxItemPool* ) const
return new SwFmtRefMark( *this );
}
+void SwFmtRefMark::Modify(SfxPoolItem const* pOld, SfxPoolItem const* pNew)
+{
+ NotifyClients(pOld, pNew);
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached UNO object
+ SetXRefMark(css::uno::Reference<css::text::XTextContent>(0));
+ }
+}
+
void SwFmtRefMark::InvalidateRefMark()
{
SwPtrMsgPoolItem const item(RES_REMOVE_UNO_OBJECT,
diff --git a/sw/source/core/unocore/unocoll.cxx b/sw/source/core/unocore/unocoll.cxx
index d9540975b365..4f3a825330b3 100644
--- a/sw/source/core/unocore/unocoll.cxx
+++ b/sw/source/core/unocore/unocoll.cxx
@@ -669,7 +669,7 @@ uno::Reference< uno::XInterface > SwXServiceProvider::MakeInstance(sal_uInt16
break;
case SW_SERVICE_REFERENCE_MARK :
- xRet = (cppu::OWeakObject*)new SwXReferenceMark(0, 0);
+ xRet = SwXReferenceMark::CreateXReferenceMark(*pDoc, 0);
break;
case SW_SERVICE_STYLE_CHARACTER_STYLE:
case SW_SERVICE_STYLE_PARAGRAPH_STYLE:
@@ -1912,10 +1912,11 @@ uno::Any SwXReferenceMarks::getByIndex(sal_Int32 nIndex)
uno::Reference< XTextContent > xRef;
if(0 <= nIndex && nIndex < USHRT_MAX)
{
- const SwFmtRefMark* pMark = GetDoc()->GetRefMark( (sal_uInt16) nIndex );
+ SwFmtRefMark *const pMark = const_cast<SwFmtRefMark*>(
+ GetDoc()->GetRefMark(static_cast<sal_uInt16>(nIndex)));
if(pMark)
{
- xRef = SwXReferenceMarks::GetObject( GetDoc(), pMark );
+ xRef = SwXReferenceMark::CreateXReferenceMark(*GetDoc(), pMark);
aRet.setValue(&xRef, cppu::UnoType<XTextContent>::get());
}
}
@@ -1931,10 +1932,12 @@ uno::Any SwXReferenceMarks::getByName(const OUString& rName)
uno::Any aRet;
if(IsValid())
{
- const SwFmtRefMark* pMark = GetDoc()->GetRefMark(rName);
+ SwFmtRefMark *const pMark =
+ const_cast<SwFmtRefMark*>(GetDoc()->GetRefMark(rName));
if(pMark)
{
- uno::Reference< XTextContent > xRef = SwXReferenceMarks::GetObject( GetDoc(), pMark );
+ uno::Reference<XTextContent> const xRef =
+ SwXReferenceMark::CreateXReferenceMark(*GetDoc(), pMark);
aRet.setValue(&xRef, cppu::UnoType<XTextContent>::get());
}
else
@@ -1984,12 +1987,6 @@ sal_Bool SwXReferenceMarks::hasElements(void) throw( uno::RuntimeException, std:
return 0 != GetDoc()->GetRefMarks();
}
-SwXReferenceMark* SwXReferenceMarks::GetObject( SwDoc* pDoc, const SwFmtRefMark* pMark )
-{
- return SwXReferenceMark::CreateXReferenceMark(
- *pDoc, *const_cast<SwFmtRefMark*>(pMark));
-}
-
void SwUnoCollection::Invalidate()
{
bObjectValid = false;
diff --git a/sw/source/core/unocore/unocrsrhelper.cxx b/sw/source/core/unocore/unocrsrhelper.cxx
index 71610597968c..a80c496589bd 100644
--- a/sw/source/core/unocore/unocrsrhelper.cxx
+++ b/sw/source/core/unocore/unocrsrhelper.cxx
@@ -632,7 +632,9 @@ bool getCrsrPropertyValue(const SfxItemPropertySimpleEntry& rEntry
if( pAny )
{ // hmm... can only return 1 here
const SwFmtRefMark& rRef = (*marks.begin())->GetRefMark();
- uno::Reference< XTextContent > xRef = SwXReferenceMarks::GetObject( rPam.GetDoc(), &rRef );
+ uno::Reference<XTextContent> const xRef =
+ SwXReferenceMark::CreateXReferenceMark(*rPam.GetDoc(),
+ const_cast<SwFmtRefMark*>(&rRef));
pAny->setValue(&xRef, cppu::UnoType<XTextContent>::get());
}
}
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
index 3b5cba4d6a68..5e02a0200b1e 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -496,7 +496,7 @@ lcl_CreateRefMarkPortion(
Reference<XTextContent> xContent;
if (!xContent.is())
{
- xContent = new SwXReferenceMark(pDoc, &rRefMark);
+ xContent = SwXReferenceMark::CreateXReferenceMark(*pDoc, &rRefMark);
}
SwXTextPortion* pPortion = 0;
diff --git a/sw/source/core/unocore/unorefmk.cxx b/sw/source/core/unocore/unorefmk.cxx
index abcb746843ce..10f0a067b872 100644
--- a/sw/source/core/unocore/unorefmk.cxx
+++ b/sw/source/core/unocore/unorefmk.cxx
@@ -108,25 +108,26 @@ SwXReferenceMark::~SwXReferenceMark()
{
}
-SwXReferenceMark *
-SwXReferenceMark::GetReferenceMark(
- SwModify const& /*rUnoCB*/, SwFmtRefMark const& /*rMarkFmt*/)
-{
- // #i105557#: do not iterate over the registered clients: race condition
- // to do this properly requires the SwXReferenceMark to register at the
- // SwFmtRefMark directly, not at the unocallback
- return 0;
-}
-
-SwXReferenceMark *
+uno::Reference<text::XTextContent>
SwXReferenceMark::CreateXReferenceMark(
- SwDoc & rDoc, SwFmtRefMark & rMarkFmt)
+ SwDoc & rDoc, SwFmtRefMark *const pMarkFmt)
{
- SwXReferenceMark *const pXMark(
- GetReferenceMark(rMarkFmt, rMarkFmt) );
- return (pXMark)
- ? pXMark
- : new SwXReferenceMark(&rDoc, &rMarkFmt);
+ // i#105557: do not iterate over the registered clients: race condition
+ uno::Reference<text::XTextContent> xMark;
+ if (pMarkFmt)
+ {
+ xMark = pMarkFmt->GetXRefMark();
+ }
+ if (!xMark.is())
+ {
+ SwXReferenceMark *const pMark(new SwXReferenceMark(&rDoc, pMarkFmt));
+ xMark.set(pMark);
+ if (pMarkFmt)
+ {
+ pMarkFmt->SetXRefMark(xMark);
+ }
+ }
+ return xMark;
}
namespace