desktop/source/lib/init.cxx | 53 ++++++++++++++++++++++++------- include/salhelper/timer.hxx | 8 ++++ salhelper/source/gcc3.map | 5 ++ salhelper/source/timer.cxx | 75 ++++++++++++++++++++++++++++++++++++-------- 4 files changed, 116 insertions(+), 25 deletions(-)
New commits: commit 645746365891acf277534c62f2a3fc0c8ccd7f89 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Wed May 21 17:53:20 2025 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Thu May 22 11:57:18 2025 +0200 join restartable threads on large trimMemory effort Change-Id: Ibbb1471fb1436e7894cdc6946410a88e52dd50c9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185627 Reviewed-by: Michael Meeks <michael.me...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> (cherry picked from commit b5f44b5f68dcb814771a6eec29ed92fdb56d93d2) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185642 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 7e312ad1a3ab..40e522c635fe 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -3336,6 +3336,18 @@ static char* lo_extractDocumentStructureRequest(LibreOfficeKit* /*pThis*/, const return strdup("{ }"); } +namespace { + +enum class JoinThreads +{ + ALL, + RESTARTS_ON_DEMAND +}; + +} + +static int joinThreads(JoinThreads eCategory); + static void lo_trimMemory(LibreOfficeKit* /* pThis */, int nTarget) { vcl::lok::trimMemory(nTarget); @@ -3368,6 +3380,10 @@ static void lo_trimMemory(LibreOfficeKit* /* pThis */, int nTarget) } } } + + // When more agressively reclaiming memory then shutdown threads which + // will restart on demand. + joinThreads(JoinThreads::RESTARTS_ON_DEMAND); } if (nTarget > 1000) @@ -3545,8 +3561,7 @@ static void lo_stopURP(LibreOfficeKit* /* pThis */, static_cast<FunctionBasedURPConnection*>(pFunctionBasedURPConnection)->close(); } - -static int lo_joinThreads(LibreOfficeKit* /* pThis */) +static int joinThreads(JoinThreads eCategory) { comphelper::ThreadPool &pool = comphelper::ThreadPool::getSharedOptimalPool(); if (!pool.joinThreadsIfIdle()) @@ -3560,17 +3575,20 @@ static int lo_joinThreads(LibreOfficeKit* /* pThis */) if (joinable && !joinable->joinThreads()) return 0; - auto ucpWebdav = xContext->getServiceManager()->createInstanceWithContext( - "com.sun.star.ucb.WebDAVManager", xContext); - joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable *>(ucpWebdav.get()); - if (joinable && !joinable->joinThreads()) - return 0; + if (eCategory == JoinThreads::ALL) + { + auto ucpWebdav = xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.ucb.WebDAVManager", xContext); + joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable *>(ucpWebdav.get()); + if (joinable && !joinable->joinThreads()) + return 0; - auto progressThread = xContext->getServiceManager()->createInstanceWithContext( - "com.sun.star.task.StatusIndicatorFactory", xContext); - joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable *>(progressThread.get()); - if (joinable && !joinable->joinThreads()) - return 0; + auto progressThread = xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.task.StatusIndicatorFactory", xContext); + joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable *>(progressThread.get()); + if (joinable && !joinable->joinThreads()) + return 0; + } // Ensure configmgr's write thread is down css::uno::Reference< css::util::XFlushable >( @@ -3578,11 +3596,17 @@ static int lo_joinThreads(LibreOfficeKit* /* pThis */) comphelper::getProcessComponentContext()), css::uno::UNO_QUERY_THROW)->flush(); - salhelper::Timer::joinThread(); + if (eCategory == JoinThreads::ALL) + salhelper::Timer::joinThread(); return 1; } +static int lo_joinThreads(LibreOfficeKit* /* pThis */) +{ + return joinThreads(JoinThreads::ALL); +} + static void lo_startThreads(LibreOfficeKit* /* pThis */) { salhelper::Timer::startThread(); commit 011760896551817d4fe8018214eff6d011bb385a Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Fri Mar 14 19:29:11 2025 +0000 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Thu May 22 11:57:11 2025 +0200 Timer - shutdown and re-start salhelper::Timer thread. Necessary for lok background save. Change-Id: Ib78f67f124dcd5b2a8b50c65ea58a9e1eb894ade Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182931 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit 79197949d757c40f750406f59e85d6efe02bf584) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185641 diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 268ea05974e3..7e312ad1a3ab 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -77,6 +77,7 @@ #include <rtl/uri.hxx> #include <svl/cryptosign.hxx> #include <linguistic/misc.hxx> +#include <salhelper/timer.hxx> #include <cppuhelper/bootstrap.hxx> #include <comphelper/random.hxx> #include <comphelper/base64.hxx> @@ -3577,11 +3578,15 @@ static int lo_joinThreads(LibreOfficeKit* /* pThis */) comphelper::getProcessComponentContext()), css::uno::UNO_QUERY_THROW)->flush(); + salhelper::Timer::joinThread(); + return 1; } static void lo_startThreads(LibreOfficeKit* /* pThis */) { + salhelper::Timer::startThread(); + auto ucpWebdav = xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.ucb.WebDAVManager", xContext); auto joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable *>(ucpWebdav.get()); diff --git a/include/salhelper/timer.hxx b/include/salhelper/timer.hxx index 8c0ce5d3a2bc..3fa81785aefe 100644 --- a/include/salhelper/timer.hxx +++ b/include/salhelper/timer.hxx @@ -177,6 +177,14 @@ public: */ TTimeValue SAL_CALL getRemainingTime() const; + /** Internal method to shutdown the timer thread + */ + static void SAL_CALL joinThread(); + + /** Internal method to re-start the timer thread if necessary + */ + static void SAL_CALL startThread(); + protected: /** Destructor. diff --git a/salhelper/source/gcc3.map b/salhelper/source/gcc3.map index 3d0d90d4aae0..b1bbad779b31 100644 --- a/salhelper/source/gcc3.map +++ b/salhelper/source/gcc3.map @@ -131,6 +131,11 @@ LIBO_UDK_3.6 { # symbols available in >= LibO 3.6 # non-virtual thunk to salhelper::Thread::run() } UDK_3.1; +PRIVATE_1.0 { + _ZN9salhelper5Timer10joinThreadEv; + _ZN9salhelper5Timer11startThreadEv; +}; + # Unique libstdc++ symbols: GLIBCXX_3.4 { global: diff --git a/salhelper/source/timer.cxx b/salhelper/source/timer.cxx index 07510f228cde..7a83149c867c 100644 --- a/salhelper/source/timer.cxx +++ b/salhelper/source/timer.cxx @@ -20,16 +20,15 @@ #include <osl/thread.hxx> -#include <condition_variable> #include <mutex> +#include <condition_variable> using namespace salhelper; class salhelper::TimerManager final : public osl::Thread { public: - TimerManager(); - + TimerManager(salhelper::Timer* &pHead, std::mutex &Lock); ~TimerManager(); /// register timer @@ -48,24 +47,65 @@ protected: /// Checking and triggering of a timer event void checkForTimeout(); - /// sorted-queue data - salhelper::Timer* m_pHead; + salhelper::Timer* &m_pHead; bool m_terminate; /// List Protection - std::mutex m_Lock; + std::mutex &m_Lock; /// Signal the insertion of a timer std::condition_variable m_notEmpty; /// "Singleton Pattern" //static salhelper::TimerManager* m_pManager; - }; -namespace +namespace { +class TimerManagerImpl final { - salhelper::TimerManager& getTimerManager() + std::mutex m_Lock; // shared lock with each impl. thread + salhelper::Timer* m_pHead; // the underlying shared queue + std::shared_ptr<TimerManager> m_pImpl; + +public: + TimerManagerImpl() : m_pHead(nullptr) { } + + void joinThread() + { + m_pImpl.reset(); + } + + void startThread() + { + std::lock_guard Guard(m_Lock); + if (m_pHead) + ensureThread(); + } + + std::shared_ptr<TimerManager> ensureThread() + { + if (!m_pImpl) + m_pImpl.reset(new TimerManager(m_pHead, m_Lock)); + return m_pImpl; + } + + void registerTimer(salhelper::Timer* pTimer) { - static salhelper::TimerManager aManager; + ensureThread()->registerTimer(pTimer); + } + + void unregisterTimer(salhelper::Timer * pTimer) + { + ensureThread()->unregisterTimer(pTimer); + } + + bool lookupTimer(const salhelper::Timer* pTimer) + { + return ensureThread()->lookupTimer(pTimer); + } +}; + + TimerManagerImpl& getTimerManager() + { + static TimerManagerImpl aManager; return aManager; } } @@ -195,6 +235,16 @@ TTimeValue Timer::getRemainingTime() const return TTimeValue(secs, nsecs); } +void Timer::joinThread() +{ + getTimerManager().joinThread(); +} + +void Timer::startThread() +{ + getTimerManager().startThread(); +} + /** The timer manager cleanup has been removed (no thread is killed anymore), so the thread leaks. @@ -205,8 +255,8 @@ TTimeValue Timer::getRemainingTime() const when there are no timers anymore ! **/ -TimerManager::TimerManager() : - m_pHead(nullptr), m_terminate(false) +TimerManager::TimerManager(salhelper::Timer* &pHead, std::mutex &Lock) : + m_pHead(pHead), m_terminate(false), m_Lock(Lock) { // start thread create(); @@ -387,7 +437,6 @@ void TimerManager::run() checkForTimeout(); } - } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */