desktop/inc/lib/init.hxx | 20 +++++--------- desktop/source/lib/init.cxx | 62 +++++++++++++++++++------------------------- 2 files changed, 36 insertions(+), 46 deletions(-)
New commits: commit d78938768c6f8dbc0917184c8daa0c381400bff7 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Fri May 3 13:59:44 2024 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Fri May 3 20:10:14 2024 +0200 flush CallbackFlushHandler queue via PostUserEvent instead of Idle+Timer Looking at when Invoke was called from Idle (or from auxiliary Timeout if there was no chance to run the Idle within 100ms) and when duplicate merging and modification of the queue is done before getting dispatched and cleared; Then the pattern is that duplicates are collected and merged during the current block of events to be processed, and dispatching the flush via PostUserEvent instead gives the same results. During startup, scheduling via PostUserEvent drops the need to have the aux timeout, and while the number of messages seen in the first queue flush (now via PostUserEvent instead of 100ms Timer) remain the same as before, subsequent queue flushes can get processed earlier while smaller, though typically at the same time as before once the document is fully loaded. Change-Id: I64c6bbc3dea9fb3a512c2a9521303a8f143d4a89 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167064 Reviewed-by: Michael Meeks <michael.me...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 323a508098f5..536faf00aff9 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -93,12 +93,11 @@ namespace desktop { }; /// One instance of this per view, handles flushing callbacks - class DESKTOP_DLLPUBLIC CallbackFlushHandler final : public Idle, public SfxLokCallbackInterface + class DESKTOP_DLLPUBLIC CallbackFlushHandler final : public SfxLokCallbackInterface { public: explicit CallbackFlushHandler(LibreOfficeKitDocument* pDocument, LibreOfficeKitCallback pCallback, void* pData); virtual ~CallbackFlushHandler() override; - virtual void Invoke() override; // TODO This should be dropped and the binary libreOfficeKitViewCallback() variants should be called? void queue(const int type, const OString& data); @@ -189,7 +188,8 @@ namespace desktop { typedef std::vector<int> queue_type1; typedef std::vector<CallbackData> queue_type2; - void startTimer(); + void scheduleFlush(); + void invoke(); bool removeAll(int type); bool removeAll(int type, const std::function<bool (const CallbackData&)>& rTestFunc); bool processInvalidateTilesEvent(int type, CallbackData& aCallbackData); @@ -200,6 +200,8 @@ namespace desktop { void enqueueUpdatedTypes(); void enqueueUpdatedType( int type, const SfxViewShell* sourceViewShell, int viewId ); + void stop(); + /** we frequently want to scan the queue, and mostly when we do so, we only care about the element type so we split the queue in 2 to make the scanning cache friendly. */ queue_type1 m_queue1; @@ -230,18 +232,12 @@ namespace desktop { LibreOfficeKitDocument* m_pDocument; int m_viewId = -1; // view id of the associated SfxViewShell LibreOfficeKitCallback m_pCallback; + ImplSVEvent* m_pFlushEvent; void *m_pData; int m_nDisableCallbacks; std::recursive_mutex m_mutex; - class TimeoutIdle : public Timer - { - public: - TimeoutIdle( CallbackFlushHandler* handler ); - virtual void Invoke() override; - private: - CallbackFlushHandler* mHandler; - }; - TimeoutIdle m_TimeoutIdle; + + DECL_LINK(FlushQueue, void*, void); }; struct DESKTOP_DLLPUBLIC LibLODocument_Impl : public _LibreOfficeKitDocument diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 081166baeb0b..d5476cfe7666 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1524,32 +1524,14 @@ static OUString getGenerator() extern "C" { -CallbackFlushHandler::TimeoutIdle::TimeoutIdle( CallbackFlushHandler* handler ) - : Timer( "lokit timer callback" ) - , mHandler( handler ) -{ - // A second timer with higher priority, it'll ensure we flush in reasonable time if we get too busy - // to get POST_PAINT priority processing. Otherwise it could take a long time to flush. - SetPriority(TaskPriority::DEFAULT); - SetTimeout( 100 ); // 100 ms -} - -void CallbackFlushHandler::TimeoutIdle::Invoke() -{ - mHandler->Invoke(); -} - // One of these is created per view to handle events cf. doc_registerCallback CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, LibreOfficeKitCallback pCallback, void* pData) - : Idle( "lokit idle callback" ), - m_pDocument(pDocument), + : m_pDocument(pDocument), m_pCallback(pCallback), + m_pFlushEvent(nullptr), m_pData(pData), - m_nDisableCallbacks(0), - m_TimeoutIdle( this ) + m_nDisableCallbacks(0) { - SetPriority(TaskPriority::POST_PAINT); - // Add the states that are safe to skip duplicates on, even when // not consequent (i.e. do no emit them if unchanged from last). m_states.emplace(LOK_CALLBACK_TEXT_SELECTION, "NIL"_ostr); @@ -1568,9 +1550,18 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li m_states.emplace(LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE, "NIL"_ostr); } +void CallbackFlushHandler::stop() +{ + if (m_pFlushEvent) + { + Application::RemoveUserEvent(m_pFlushEvent); + m_pFlushEvent = nullptr; + } +} + CallbackFlushHandler::~CallbackFlushHandler() { - Stop(); + stop(); } CallbackFlushHandler::queue_type2::iterator CallbackFlushHandler::toQueue2(CallbackFlushHandler::queue_type1::iterator pos) @@ -1592,7 +1583,7 @@ void CallbackFlushHandler::setUpdatedType( int nType, bool value ) m_updatedTypes.resize( nType + 1 ); // new are default-constructed, i.e. false m_updatedTypes[ nType ] = value; if(value) - startTimer(); + scheduleFlush(); } void CallbackFlushHandler::resetUpdatedType( int nType ) @@ -1608,7 +1599,7 @@ void CallbackFlushHandler::setUpdatedTypePerViewId( int nType, int nViewId, int types.resize( nType + 1 ); // new are default-constructed, i.e. 'set' is false types[ nType ] = PerViewIdData{ value, nSourceViewId }; if(value) - startTimer(); + scheduleFlush(); } void CallbackFlushHandler::resetUpdatedTypePerViewId( int nType, int nViewId ) @@ -1685,7 +1676,7 @@ void CallbackFlushHandler::dumpState(rtl::OStringBuffer &rState) void CallbackFlushHandler::libreOfficeKitViewAddPendingInvalidateTiles() { // Invoke() will call flushPendingLOKInvalidateTiles(), so just make sure the timer is active. - startTimer(); + scheduleFlush(); } void CallbackFlushHandler::queue(const int type, const OString& data) @@ -1998,7 +1989,7 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) #endif lock.unlock(); - startTimer(); + scheduleFlush(); } bool CallbackFlushHandler::processInvalidateTilesEvent(int type, CallbackData& aCallbackData) @@ -2376,7 +2367,7 @@ void CallbackFlushHandler::enqueueUpdatedType( int type, const SfxViewShell* vie << "] to have " << m_queue1.size() << " entries."); } -void CallbackFlushHandler::Invoke() +void CallbackFlushHandler::invoke() { comphelper::ProfileZone aZone("CallbackFlushHandler::Invoke"); @@ -2484,16 +2475,19 @@ void CallbackFlushHandler::Invoke() m_queue1.clear(); m_queue2.clear(); - Stop(); - m_TimeoutIdle.Stop(); + stop(); } -void CallbackFlushHandler::startTimer() +void CallbackFlushHandler::scheduleFlush() { - if (!IsActive()) - Start(); - if (!m_TimeoutIdle.IsActive()) - m_TimeoutIdle.Start(); + if (!m_pFlushEvent) + m_pFlushEvent = Application::PostUserEvent(LINK(this, CallbackFlushHandler, FlushQueue)); +} + +IMPL_LINK_NOARG(CallbackFlushHandler, FlushQueue, void*, void) +{ + m_pFlushEvent = nullptr; + invoke(); } bool CallbackFlushHandler::removeAll(int type)