diff --git a/drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx b/drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx index 96fd72eb25ca..a24816ad5f3a 100644 --- a/drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx +++ b/drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D.cxx @@ -70,32 +70,38 @@ BufferedDecompositionGroupPrimitive2D::getBuffered2DDecomposition() const void BufferedDecompositionGroupPrimitive2D::setBuffered2DDecomposition(Primitive2DContainer&& rNew) { - if (0 != maCallbackSeconds) + if (0 == maCallbackSeconds) { - if (maCallbackTimer.is()) - { - if (rNew.empty()) - { - // stop timer - maCallbackTimer->stop(); - } - else - { - // decomposition changed, touch - maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); - if (!maCallbackTimer->isTicking()) - maCallbackTimer->start(); - } - } - else if (!rNew.empty()) - { - // decomposition defined/set/changed, init & start timer - maCallbackTimer.set(new LocalCallbackTimer(*this)); - maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); - maCallbackTimer->start(); - } + // no flush used, just set + maBuffered2DDecomposition = std::move(rNew); + return; } + if (maCallbackTimer.is()) + { + if (rNew.empty()) + { + // stop timer + maCallbackTimer->stop(); + } + else + { + // decomposition changed, touch + maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); + if (!maCallbackTimer->isTicking()) + maCallbackTimer->start(); + } + } + else if (!rNew.empty()) + { + // decomposition defined/set/changed, init & start timer + maCallbackTimer.set(new LocalCallbackTimer(*this)); + maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); + maCallbackTimer->start(); + } + + // tdf#158913 need to secure change when flush/multithreading is in use + std::lock_guard Guard(maCallbackLock); maBuffered2DDecomposition = std::move(rNew); } @@ -103,6 +109,7 @@ BufferedDecompositionGroupPrimitive2D::BufferedDecompositionGroupPrimitive2D( Primitive2DContainer&& aChildren) : GroupPrimitive2D(std::move(aChildren)) , maCallbackTimer() + , maCallbackLock() , maCallbackSeconds(0) { } @@ -129,6 +136,17 @@ void BufferedDecompositionGroupPrimitive2D::get2DDecomposition( std::move(aNewSequence)); } + if (0 == maCallbackSeconds) + { + // no flush/multithreading is in use, just call + rVisitor.visit(getBuffered2DDecomposition()); + return; + } + + // tdf#158913 need to secure 'visit' when flush/multithreading is in use, + // so that the local non-ref-Counted instance of the decomposition gets not + // manipulated (e.g. deleted) + std::lock_guard Guard(maCallbackLock); rVisitor.visit(getBuffered2DDecomposition()); } diff --git a/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx b/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx index c7f3b78477b0..22b6450e7f2d 100644 --- a/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx +++ b/drawinglayer/source/primitive2d/BufferedDecompositionPrimitive2D.cxx @@ -69,38 +69,45 @@ const Primitive2DContainer& BufferedDecompositionPrimitive2D::getBuffered2DDecom void BufferedDecompositionPrimitive2D::setBuffered2DDecomposition(Primitive2DContainer&& rNew) { - if (0 != maCallbackSeconds) + if (0 == maCallbackSeconds) { - if (maCallbackTimer.is()) - { - if (rNew.empty()) - { - // stop timer - maCallbackTimer->stop(); - } - else - { - // decomposition changed, touch - maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); - if (!maCallbackTimer->isTicking()) - maCallbackTimer->start(); - } - } - else if (!rNew.empty()) - { - // decomposition defined/set/changed, init & start timer - maCallbackTimer.set(new LocalCallbackTimer(*this)); - maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); - maCallbackTimer->start(); - } + // no flush used, just set + maBuffered2DDecomposition = std::move(rNew); + return; } + if (maCallbackTimer.is()) + { + if (rNew.empty()) + { + // stop timer + maCallbackTimer->stop(); + } + else + { + // decomposition changed, touch + maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); + if (!maCallbackTimer->isTicking()) + maCallbackTimer->start(); + } + } + else if (!rNew.empty()) + { + // decomposition defined/set/changed, init & start timer + maCallbackTimer.set(new LocalCallbackTimer(*this)); + maCallbackTimer->setRemainingTime(salhelper::TTimeValue(maCallbackSeconds, 0)); + maCallbackTimer->start(); + } + + // tdf#158913 need to secure change when flush/multithreading is in use + std::lock_guard Guard(maCallbackLock); maBuffered2DDecomposition = std::move(rNew); } BufferedDecompositionPrimitive2D::BufferedDecompositionPrimitive2D() : maBuffered2DDecomposition() , maCallbackTimer() + , maCallbackLock() , maCallbackSeconds(0) , mnTransparenceForShadow(0) { @@ -128,6 +135,17 @@ void BufferedDecompositionPrimitive2D::get2DDecomposition( std::move(aNewSequence)); } + if (0 == maCallbackSeconds) + { + // no flush/multithreading is in use, just call + rVisitor.visit(getBuffered2DDecomposition()); + return; + } + + // tdf#158913 need to secure 'visit' when flush/multithreading is in use, + // so that the local non-ref-Counted instance of the decomposition gets not + // manipulated (e.g. deleted) + std::lock_guard Guard(maCallbackLock); rVisitor.visit(getBuffered2DDecomposition()); } diff --git a/include/drawinglayer/primitive2d/BufferedDecompositionGroupPrimitive2D.hxx b/include/drawinglayer/primitive2d/BufferedDecompositionGroupPrimitive2D.hxx index 031bd360a174..778c52c94e24 100644 --- a/include/drawinglayer/primitive2d/BufferedDecompositionGroupPrimitive2D.hxx +++ b/include/drawinglayer/primitive2d/BufferedDecompositionGroupPrimitive2D.hxx @@ -44,6 +44,7 @@ private: /// offer callback mechanism to flush buffered content timer-based ::rtl::Reference<::salhelper::Timer> maCallbackTimer; + mutable std::mutex maCallbackLock; sal_uInt16 maCallbackSeconds; protected: diff --git a/include/drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx b/include/drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx index 55ba886671e0..cc36ddb93cd5 100644 --- a/include/drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx +++ b/include/drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx @@ -71,6 +71,7 @@ private: /// offer callback mechanism to flush buffered content timer-based ::rtl::Reference<::salhelper::Timer> maCallbackTimer; + mutable std::mutex maCallbackLock; sal_uInt16 maCallbackSeconds; /// When a shadow wraps a list of primitives, this primitive wants to influence the transparency