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)

Reply via email to