[Libreoffice-commits] core.git: Branch 'libreoffice-5-3' - sdext/source

Michael Stahl mstahl at redhat.com
Thu May 25 07:27:30 UTC 2017


 sdext/source/presenter/PresenterScrollBar.cxx |    1 
 sdext/source/presenter/PresenterScrollBar.hxx |    3 
 sdext/source/presenter/PresenterTextView.cxx  |    6 +
 sdext/source/presenter/PresenterTextView.hxx  |    2 
 sdext/source/presenter/PresenterTimer.cxx     |   99 +++++++++++++++++++++++---
 sdext/source/presenter/PresenterTimer.hxx     |    2 
 6 files changed, 104 insertions(+), 9 deletions(-)

New commits:
commit 1a14a0404ef02a76cfc3b6bfd50b1c78bb150d45
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed May 24 16:14:56 2017 +0200

    rhbz#1425304 sdext: join TimerScheduler thread before shutdown
    
    Use a osl::Condition to interrupt the waiting thread, and join it.
    
    Change-Id: I638a2495afd082446c39faf9362578bd0f758d04
    (cherry picked from commit 15b033d1dd09cd1898a994a0f12e38ed5cf847cb)
    Reviewed-on: https://gerrit.libreoffice.org/37992
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sdext/source/presenter/PresenterScrollBar.cxx b/sdext/source/presenter/PresenterScrollBar.cxx
index 8cba1bcafa01..831c0ec274bb 100644
--- a/sdext/source/presenter/PresenterScrollBar.cxx
+++ b/sdext/source/presenter/PresenterScrollBar.cxx
@@ -802,6 +802,7 @@ void PresenterScrollBar::MousePressRepeater::Start (const PresenterScrollBar::Ar
         // Schedule repeated executions.
         auto pThis(shared_from_this());
         mnMousePressRepeaterTaskId = PresenterTimer::ScheduleRepeatedTask (
+            mpScrollBar->GetComponentContext(),
             [pThis] (TimeValue const& rTime) { return pThis->Callback(rTime); },
             500000000,
             250000000);
diff --git a/sdext/source/presenter/PresenterScrollBar.hxx b/sdext/source/presenter/PresenterScrollBar.hxx
index 7706ce4ea5aa..1c51194e897b 100644
--- a/sdext/source/presenter/PresenterScrollBar.hxx
+++ b/sdext/source/presenter/PresenterScrollBar.hxx
@@ -60,6 +60,9 @@ public:
 
     virtual void SAL_CALL disposing() override;
 
+    css::uno::Reference<css::uno::XComponentContext> const&
+        GetComponentContext() { return mxComponentContext; }
+
     void SetVisible (const bool bIsVisible);
 
     /** Set the bounding box of the scroll bar.
diff --git a/sdext/source/presenter/PresenterTextView.cxx b/sdext/source/presenter/PresenterTextView.cxx
index 8e3800b46479..1946696b4b89 100644
--- a/sdext/source/presenter/PresenterTextView.cxx
+++ b/sdext/source/presenter/PresenterTextView.cxx
@@ -73,6 +73,7 @@ PresenterTextView::PresenterTextView (
       mpFont(),
       maParagraphs(),
       mpCaret(new PresenterTextCaret(
+          rxContext,
           [this] (sal_Int32 const nParagraphIndex, sal_Int32 const nCharacterIndex)
               { return this->GetCaretBounds(nParagraphIndex, nCharacterIndex); },
           rInvalidator)),
@@ -1077,9 +1078,11 @@ void PresenterTextParagraph::SetupCellArray (
 //===== PresenterTextCaret ================================================----
 
 PresenterTextCaret::PresenterTextCaret (
+        uno::Reference<uno::XComponentContext> const& xContext,
     const ::std::function<css::awt::Rectangle (const sal_Int32,const sal_Int32)>& rCharacterBoundsAccess,
     const ::std::function<void (const css::awt::Rectangle&)>& rInvalidator)
-    : mnParagraphIndex(-1),
+    : m_xContext(xContext)
+    , mnParagraphIndex(-1),
       mnCharacterIndex(-1),
       mnCaretBlinkTaskId(0),
       mbIsCaretVisible(false),
@@ -1100,6 +1103,7 @@ void PresenterTextCaret::ShowCaret()
     if (mnCaretBlinkTaskId == 0)
     {
         mnCaretBlinkTaskId = PresenterTimer::ScheduleRepeatedTask (
+            m_xContext,
             [this] (TimeValue const&) { return this->InvertCaret(); },
             CaretBlinkIntervall,
             CaretBlinkIntervall);
diff --git a/sdext/source/presenter/PresenterTextView.hxx b/sdext/source/presenter/PresenterTextView.hxx
index b56bd5a85f31..9fc7fd663e1f 100644
--- a/sdext/source/presenter/PresenterTextView.hxx
+++ b/sdext/source/presenter/PresenterTextView.hxx
@@ -41,6 +41,7 @@ class PresenterTextCaret
 {
 public:
     PresenterTextCaret (
+        css::uno::Reference<css::uno::XComponentContext> const& xContext,
         const ::std::function<css::awt::Rectangle (const sal_Int32,const sal_Int32)>&
             rCharacterBoundsAccess,
         const ::std::function<void (const css::awt::Rectangle&)>&
@@ -69,6 +70,7 @@ public:
     const css::awt::Rectangle& GetBounds() const;
 
 private:
+    css::uno::Reference<css::uno::XComponentContext> const& m_xContext;
     sal_Int32 mnParagraphIndex;
     sal_Int32 mnCharacterIndex;
     sal_Int32 mnCaretBlinkTaskId;
diff --git a/sdext/source/presenter/PresenterTimer.cxx b/sdext/source/presenter/PresenterTimer.cxx
index e9d3117ba323..6d4897642c42 100644
--- a/sdext/source/presenter/PresenterTimer.cxx
+++ b/sdext/source/presenter/PresenterTimer.cxx
@@ -18,10 +18,15 @@
  */
 
 #include "PresenterTimer.hxx"
+
 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+
 #include <osl/doublecheckedlocking.h>
 #include <osl/thread.hxx>
+#include <osl/conditn.hxx>
 
 #include <algorithm>
 #include <iterator>
@@ -71,7 +76,8 @@ class TimerScheduler
       public ::osl::Thread
 {
 public:
-    static std::shared_ptr<TimerScheduler> Instance();
+    static std::shared_ptr<TimerScheduler> Instance(
+        uno::Reference<uno::XComponentContext> const& xContext);
     static SharedTimerTask CreateTimerTask (
         const PresenterTimer::Task& rTask,
         const TimeValue& rDueTime,
@@ -90,6 +96,9 @@ public:
     static sal_Int64 ConvertFromTimeValue (
         const TimeValue& rTimeValue);
 
+    static void NotifyTermination();
+    static bool HasInstance() { return mpInstance != nullptr; }
+
 private:
     static std::shared_ptr<TimerScheduler> mpInstance;
     static ::osl::Mutex maInstanceMutex;
@@ -101,8 +110,10 @@ private:
     TaskContainer maScheduledTasks;
     ::osl::Mutex maCurrentTaskMutex;
     SharedTimerTask mpCurrentTask;
+    ::osl::Condition m_Shutdown;
 
-    TimerScheduler();
+    TimerScheduler(
+        uno::Reference<uno::XComponentContext> const& xContext);
     virtual ~TimerScheduler() override;
     class Deleter {public: void operator () (TimerScheduler* pScheduler) { delete pScheduler; } };
     friend class Deleter;
@@ -111,15 +122,42 @@ private:
     virtual void SAL_CALL onTerminated() override { mpLateDestroy.reset(); }
 };
 
+class TerminateListener
+    : public ::cppu::WeakImplHelper<frame::XTerminateListener>
+{
+    virtual ~TerminateListener() override
+    {
+        assert(!TimerScheduler::HasInstance());
+    }
+
+    virtual void SAL_CALL disposing(lang::EventObject const&)
+        throw (uno::RuntimeException, std::exception) override
+    {
+    }
+
+    virtual void SAL_CALL queryTermination(lang::EventObject const&)
+        throw (uno::RuntimeException, std::exception) override
+    {
+    }
+
+    virtual void SAL_CALL notifyTermination(lang::EventObject const&)
+        throw (uno::RuntimeException, std::exception) override
+    {
+        TimerScheduler::NotifyTermination();
+    }
+};
+
 } // end of anonymous namespace
 
 //===== PresenterTimer ========================================================
 
 sal_Int32 PresenterTimer::ScheduleRepeatedTask (
+    const uno::Reference<uno::XComponentContext>& xContext,
     const Task& rTask,
     const sal_Int64 nDelay,
     const sal_Int64 nIntervall)
 {
+    assert(xContext.is());
     TimeValue aCurrentTime;
     if (TimerScheduler::GetCurrentTime(aCurrentTime))
     {
@@ -128,7 +166,7 @@ sal_Int32 PresenterTimer::ScheduleRepeatedTask (
             aDueTime,
             TimerScheduler::ConvertFromTimeValue (aCurrentTime) + nDelay);
         SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, aDueTime, nIntervall));
-        TimerScheduler::Instance()->ScheduleTask(pTask);
+        TimerScheduler::Instance(xContext)->ScheduleTask(pTask);
         return pTask->mnTaskId;
     }
 
@@ -137,7 +175,11 @@ sal_Int32 PresenterTimer::ScheduleRepeatedTask (
 
 void PresenterTimer::CancelTask (const sal_Int32 nTaskId)
 {
-    return TimerScheduler::Instance()->CancelTask(nTaskId);
+    auto const pInstance(TimerScheduler::Instance(nullptr));
+    if (pInstance)
+    {
+        pInstance->CancelTask(nTaskId);
+    }
 }
 
 //===== TimerScheduler ========================================================
@@ -146,23 +188,33 @@ std::shared_ptr<TimerScheduler> TimerScheduler::mpInstance;
 ::osl::Mutex TimerScheduler::maInstanceMutex;
 sal_Int32 TimerScheduler::mnTaskId = PresenterTimer::NotAValidTaskId;
 
-std::shared_ptr<TimerScheduler> TimerScheduler::Instance()
+std::shared_ptr<TimerScheduler> TimerScheduler::Instance(
+    uno::Reference<uno::XComponentContext> const& xContext)
 {
     ::osl::MutexGuard aGuard (maInstanceMutex);
     if (mpInstance.get() == nullptr)
     {
-        mpInstance.reset(new TimerScheduler(), TimerScheduler::Deleter());
+        if (!xContext.is())
+            return nullptr;
+        mpInstance.reset(new TimerScheduler(xContext), TimerScheduler::Deleter());
         mpInstance->create();
     }
     return mpInstance;
 }
 
-TimerScheduler::TimerScheduler()
+TimerScheduler::TimerScheduler(
+        uno::Reference<uno::XComponentContext> const& xContext)
     : maTaskContainerMutex(),
       maScheduledTasks(),
       maCurrentTaskMutex(),
       mpCurrentTask()
 {
+    uno::Reference<frame::XDesktop> const xDesktop(
+            frame::Desktop::create(xContext));
+    uno::Reference<frame::XTerminateListener> const xListener(
+            new TerminateListener);
+    // assuming the desktop can take ownership
+    xDesktop->addTerminateListener(xListener);
 }
 
 TimerScheduler::~TimerScheduler()
@@ -222,6 +274,33 @@ void TimerScheduler::CancelTask (const sal_Int32 nTaskId)
     // Let the main-loop cleanup in its own time
 }
 
+void TimerScheduler::NotifyTermination()
+{
+    std::shared_ptr<TimerScheduler> const pInstance(TimerScheduler::mpInstance);
+    if (!pInstance)
+    {
+        return;
+    }
+
+    {
+        ::osl::MutexGuard aGuard(pInstance->maTaskContainerMutex);
+        pInstance->maScheduledTasks.clear();
+    }
+
+    {
+        ::osl::MutexGuard aGuard(pInstance->maCurrentTaskMutex);
+        if (pInstance->mpCurrentTask)
+        {
+            pInstance->mpCurrentTask->mbIsCanceled = true;
+        }
+    }
+
+    pInstance->m_Shutdown.set();
+
+    // rhbz#1425304 join thread before shutdown
+    pInstance->join();
+}
+
 void SAL_CALL TimerScheduler::run()
 {
     osl_setThreadName("sdext::presenter::TimerScheduler");
@@ -269,7 +348,8 @@ void SAL_CALL TimerScheduler::run()
             // Wait until the first task becomes due.
             TimeValue aTimeValue;
             ConvertToTimeValue(aTimeValue, nDifference);
-            wait(aTimeValue);
+            // wait on condition variable, so the thread can be stopped
+            m_Shutdown.wait(&aTimeValue);
         }
         else
         {
@@ -381,7 +461,9 @@ PresenterClockTimer::PresenterClockTimer (const Reference<XComponentContext>& rx
       mnTimerTaskId(PresenterTimer::NotAValidTaskId),
       mbIsCallbackPending(false),
       mxRequestCallback()
+    , m_xContext(rxContext)
 {
+    assert(m_xContext.is());
     Reference<lang::XMultiComponentFactory> xFactory (
         rxContext->getServiceManager(), UNO_QUERY);
     if (xFactory.is())
@@ -416,6 +498,7 @@ void PresenterClockTimer::AddListener (const SharedListener& rListener)
     if (mnTimerTaskId==PresenterTimer::NotAValidTaskId)
     {
         mnTimerTaskId = PresenterTimer::ScheduleRepeatedTask(
+            m_xContext,
             [this] (TimeValue const& rTime) { return this->CheckCurrentTime(rTime); },
             0,
             250000000 /*ns*/);
diff --git a/sdext/source/presenter/PresenterTimer.hxx b/sdext/source/presenter/PresenterTimer.hxx
index 6b6ce0eef029..48784970b2a8 100644
--- a/sdext/source/presenter/PresenterTimer.hxx
+++ b/sdext/source/presenter/PresenterTimer.hxx
@@ -57,6 +57,7 @@ public:
         nIntervall ns long until CancelTask is called.
     */
     static sal_Int32 ScheduleRepeatedTask (
+        const css::uno::Reference<css::uno::XComponentContext>& xContext,
         const Task& rTask,
         const sal_Int64 nFirst,
         const sal_Int64 nIntervall);
@@ -108,6 +109,7 @@ private:
     sal_Int32 mnTimerTaskId;
     bool mbIsCallbackPending;
     css::uno::Reference<css::awt::XRequestCallback> mxRequestCallback;
+    const css::uno::Reference<css::uno::XComponentContext> m_xContext;
 
     PresenterClockTimer (
         const css::uno::Reference<css::uno::XComponentContext>& rxContext);


More information about the Libreoffice-commits mailing list