summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2016-07-01 15:10:00 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2018-08-09 13:19:52 +0200
commit2f91c89baae9b0cf9e11cff02cf56338ebdda177 (patch)
treed6b76582a6acd7a123b39aed485f31cca1241548
parent6296e5ff06acb09b61ce731c6f820f35a695ee8a (diff)
sw: tdf#50613 fix async chart load handling
Especially if synchronous loading is requested, an async worker is on the way and we would need to 'wait' for the data. Change-Id: I20f9938738c1b46bda6b9a7f5a761e82153aed3b
-rw-r--r--sw/inc/ndole.hxx2
-rw-r--r--sw/source/core/ole/ndole.cxx88
2 files changed, 63 insertions, 27 deletions
diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index b6af9fb81b59..9f90c7ddad46 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -45,7 +45,7 @@ class SW_DLLPUBLIC SwOLEObj
// eventually buffered data if it is a chart OLE
drawinglayer::primitive2d::Primitive2DContainer m_aPrimitive2DSequence;
basegfx::B2DRange m_aRange;
- class DeflateData* m_aDeflateData;
+ class DeflateData* m_pDeflateData;
SwOLEObj( const SwOLEObj& rObj ) = delete;
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index d9cee6150602..903d96814bc1 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -681,18 +681,27 @@ class DeflateData
{
private:
friend class DeflateThread;
+ friend class SwOLEObj;
- const uno::Reference< frame::XModel > maXModel;
+ uno::Reference< frame::XModel > maXModel;
drawinglayer::primitive2d::Primitive2DContainer maPrimitive2DSequence;
basegfx::B2DRange maRange;
+
+ // set from the WorkerThread when done
std::atomic< bool> mbFinished;
+ // evtl.set from the SwOLEObj destructor when a WorkerThread is still active
+ // since it is not possible to kill it - let it terminate and delete the
+ // data working on itself
+ std::atomic< bool> mbKilled;
+
public:
DeflateData(const uno::Reference< frame::XModel >& rXModel)
: maXModel(rXModel),
maPrimitive2DSequence(),
maRange(),
- mbFinished(false)
+ mbFinished(false),
+ mbKilled(false)
{
}
@@ -713,11 +722,14 @@ public:
void waitFinished()
{
- const TimeValue aTimeValue(0, 100000); // 1/10th second
-
- while(!mbFinished)
+ while(!mbFinished && !mbKilled)
{
- osl_waitThread(&aTimeValue);
+ // need to wait until the load in progress is finished.
+ // to do so, Application::Yield() is needed since the execution
+ // here means that the SolarMutex is locked, but the
+ // WorkerThreads need it to be able to continue and finish
+ // the running import
+ Application::Yield();
}
}
};
@@ -726,6 +738,7 @@ public:
class DeflateThread : public comphelper::ThreadTask
{
+ // the data to work on
DeflateData& mrDeflateData;
public:
@@ -739,14 +752,24 @@ private:
{
try
{
+ // load the chart data and get the primitives
mrDeflateData.maPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
mrDeflateData.maXModel,
mrDeflateData.maRange);
+
+ // model no longer needed and done
+ mrDeflateData.maXModel.clear();
mrDeflateData.mbFinished = true;
}
catch (const uno::Exception&)
{
}
+
+ if(mrDeflateData.mbKilled)
+ {
+ // need to cleanup myself - data will not be used
+ delete &mrDeflateData;
+ }
}
};
@@ -758,7 +781,7 @@ SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) :
xOLERef( xObj ),
m_aPrimitive2DSequence(),
m_aRange(),
- m_aDeflateData(nullptr)
+ m_pDeflateData(nullptr)
{
xOLERef.Lock();
if ( xObj.is() )
@@ -775,7 +798,7 @@ SwOLEObj::SwOLEObj( const OUString &rString, sal_Int64 nAspect ) :
aName( rString ),
m_aPrimitive2DSequence(),
m_aRange(),
- m_aDeflateData(nullptr)
+ m_pDeflateData(nullptr)
{
xOLERef.Lock();
xOLERef.SetViewAspect( nAspect );
@@ -783,10 +806,12 @@ SwOLEObj::SwOLEObj( const OUString &rString, sal_Int64 nAspect ) :
SwOLEObj::~SwOLEObj()
{
- if(m_aDeflateData)
+ if(m_pDeflateData)
{
- m_aDeflateData->waitFinished();
- delete m_aDeflateData;
+ // set flag so that the worker thread will delete m_pDeflateData
+ // when finished and forget about it
+ m_pDeflateData->mbKilled = true;
+ m_pDeflateData = nullptr;
}
if( pListener )
@@ -1030,19 +1055,22 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
basegfx::B2DRange& rRange,
bool bSynchron)
{
- if(m_aDeflateData)
+ if(m_pDeflateData)
{
if(bSynchron)
{
- m_aDeflateData->waitFinished();
+ // data in high quality is requested, wait until the data is available
+ // since a WorkerThread was already started to load it
+ m_pDeflateData->waitFinished();
}
- if(m_aDeflateData->isFinished())
+ if(m_pDeflateData->isFinished())
{
- m_aPrimitive2DSequence = m_aDeflateData->getSequence();
- m_aRange = m_aDeflateData->getRange();
- delete m_aDeflateData;
- m_aDeflateData = nullptr;
+ // copy the result data and cleanup
+ m_aPrimitive2DSequence = m_pDeflateData->getSequence();
+ m_aRange = m_pDeflateData->getRange();
+ delete m_pDeflateData;
+ m_pDeflateData = nullptr;
}
}
@@ -1054,18 +1082,24 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
{
static bool bAnynchronousLoadingAllowed = true;
- if(bSynchron || !bAnynchronousLoadingAllowed)
+ if(bSynchron ||
+ !bAnynchronousLoadingAllowed ||
+ 0 == comphelper::ThreadPool::getSharedOptimalPool().getWorkerCount())
{
+ // load chart synchron in this Thread
m_aPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence(
aXModel,
m_aRange);
}
else
{
- if(!m_aDeflateData)
+ // if not yet setup, initiate and start a WorkerThread to load the chart
+ // and it's primitives asynchron. If it already works, returning nothing
+ // is okay (preview will be reused)
+ if(!m_pDeflateData)
{
- m_aDeflateData = new DeflateData(aXModel);
- DeflateThread* pNew = new DeflateThread(*m_aDeflateData);
+ m_pDeflateData = new DeflateData(aXModel);
+ DeflateThread* pNew = new DeflateThread(*m_pDeflateData);
comphelper::ThreadPool::getSharedOptimalPool().pushTask(pNew);
}
}
@@ -1074,6 +1108,7 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs
if(!m_aPrimitive2DSequence.empty() && !m_aRange.isEmpty())
{
+ // when we have data, also copy the buffered Range data as output
rRange = m_aRange;
}
@@ -1085,11 +1120,12 @@ void SwOLEObj::resetBufferedData()
m_aPrimitive2DSequence = drawinglayer::primitive2d::Primitive2DContainer();
m_aRange.reset();
- if(m_aDeflateData)
+ if(m_pDeflateData)
{
- m_aDeflateData->waitFinished();
- delete m_aDeflateData;
- m_aDeflateData = nullptr;
+ // load is in progress, wait until finished and cleanup without using it
+ m_pDeflateData->waitFinished();
+ delete m_pDeflateData;
+ m_pDeflateData = nullptr;
}
}