[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source include/editeng include/sfx2 include/test sfx2/source sw/source test/source
desktop/inc/lib/init.hxx|1 + desktop/source/lib/init.cxx |6 ++ include/editeng/outliner.hxx|1 + include/sfx2/lokcallback.hxx|3 +++ include/sfx2/viewsh.hxx |5 +++-- include/test/lokcallback.hxx|1 + sfx2/source/view/viewsh.cxx | 10 ++ sw/source/core/view/viewimp.cxx |5 - test/source/lokcallback.cxx |6 ++ 9 files changed, 35 insertions(+), 3 deletions(-) New commits: commit fc856cd46ac475222772395c522dc34058bd89b9 Author: Luboš Luňák AuthorDate: Tue Jun 28 09:42:17 2022 +0200 Commit: Miklos Vajna CommitDate: Wed Aug 31 08:37:06 2022 +0200 lok: make sure flushPendingLOKInvalidateTiles() is called SwViewShellImp::AddPendingLOKInvalidation() collects invalidations, but this was relying on something eventually calling flushPendingLOKInvalidateTiles(), which wasn't guaranteed. If e.g. a spellchecker caused an invalidation from in idle callback and nothing else changed, then the LOK callback handling code didn't know there was something pending. So add an explicit call to ensure to notify about these pending invalidations. Change-Id: I0a9cb0d5aba2fdbbac126cd8a4a3412bef1cab25 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136533 Tested-by: Jenkins CollaboraOffice Reviewed-by: Miklos Vajna diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 8b26e117c1fb..6a6f0bd350a3 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -115,6 +115,7 @@ namespace desktop { virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart) override; virtual void libreOfficeKitViewUpdatedCallback(int nType) override; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) override; +virtual void libreOfficeKitViewAddPendingInvalidateTiles() override; private: struct CallbackData diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 4abe6f2c5166..f22558d6d76e 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1477,6 +1477,12 @@ void CallbackFlushHandler::libreOfficeKitViewUpdatedCallbackPerViewId(int nType, setUpdatedTypePerViewId(nType, nViewId, nSourceViewId, true); } +void CallbackFlushHandler::libreOfficeKitViewAddPendingInvalidateTiles() +{ +// Invoke() will call flushPendingLOKInvalidateTiles(), so just make sure the timer is active. +startTimer(); +} + void CallbackFlushHandler::queue(const int type, const char* data) { CallbackData callbackData(data); diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index 8cc3e8c23247..e7e9720ad432 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -369,6 +369,7 @@ public: virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart) const = 0; virtual void libreOfficeKitViewUpdatedCallback(int nType) const = 0; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) const = 0; +virtual void libreOfficeKitViewAddPendingInvalidateTiles() = 0; virtual ViewShellId GetViewShellId() const = 0; virtual ViewShellDocId GetDocId() const = 0; /// Wrapper around SfxLokHelper::notifyOtherViews(). diff --git a/include/sfx2/lokcallback.hxx b/include/sfx2/lokcallback.hxx index 6f59402d0cec..b1799386d42b 100644 --- a/include/sfx2/lokcallback.hxx +++ b/include/sfx2/lokcallback.hxx @@ -48,6 +48,9 @@ public: virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) = 0; +// There are pending invalidate tiles calls that need to be processed. +// A call to SfxViewShell::flushPendingLOKInvalidateTiles() should be scheduled. +virtual void libreOfficeKitViewAddPendingInvalidateTiles() = 0; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index 26a2324c7ca0..f2b0bf29080a 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -340,10 +340,11 @@ public: virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const override; virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) const override; virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart) const override; -// Performs any pending calls to libreOfficeKitViewInvalidateTilesCallback() as necessary. -virtual void flushPendingLOKInvalidateTiles(); virtual void libreOfficeKitViewUpdatedCallback(int nType) const override; virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) const override; +//
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx|2 +- desktop/source/lib/init.cxx |8 2 files changed, 5 insertions(+), 5 deletions(-) New commits: commit e9dc2d59b0a362af512f4523ec7b120640ea7cf1 Author: Luboš Luňák AuthorDate: Wed Jun 8 15:23:22 2022 +0200 Commit: Andras Timar CommitDate: Thu Jun 9 21:16:23 2022 +0200 use recursive mutex for LOK queue Callbacks may be invoked while calling getLOKPayload(), which would try to lock the mutex again. I actually originally expected this possibility, as the comment and moving the data to temporaries in CallbackFlushHandler::enqueueUpdatedTypes() shows, I just didn't realize the used mutex wasn't recursive and so would deadlock. Change-Id: I2b5c4b6b4c1a3933a32ae4641830877e085f2b6c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135499 Tested-by: Jenkins Reviewed-by: Michael Meeks (cherry picked from commit 118bafcfd1ce4a26ec9df912197ebd466d1bd497) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135388 Tested-by: Andras Timar Reviewed-by: Andras Timar diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index c19e4c5b0ac1..8b26e117c1fb 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -219,7 +219,7 @@ namespace desktop { LibreOfficeKitCallback m_pCallback; void *m_pData; int m_nDisableCallbacks; -std::mutex m_mutex; +std::recursive_mutex m_mutex; class TimeoutIdle : public Timer { public: diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index e99dace9c24e..9d88234bdb21 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1464,7 +1464,7 @@ void CallbackFlushHandler::libreOfficeKitViewInvalidateTilesCallback(const tools void CallbackFlushHandler::libreOfficeKitViewUpdatedCallback(int nType) { assert(isUpdatedType( nType )); -std::unique_lock lock(m_mutex); +std::unique_lock lock(m_mutex); SAL_INFO("lok", "Updated: [" << nType << "]"); setUpdatedType(nType, true); } @@ -1472,7 +1472,7 @@ void CallbackFlushHandler::libreOfficeKitViewUpdatedCallback(int nType) void CallbackFlushHandler::libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) { assert(isUpdatedTypePerViewId( nType )); -std::unique_lock lock(m_mutex); +std::unique_lock lock(m_mutex); SAL_INFO("lok", "Updated: [" << nType << "]"); setUpdatedTypePerViewId(nType, nViewId, nSourceViewId, true); } @@ -1543,7 +1543,7 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) return; } -std::unique_lock lock(m_mutex); +std::unique_lock lock(m_mutex); // Update types should be received via the updated callbacks for performance, // getting them as normal callbacks is technically not wrong, but probably should be avoided. @@ -2138,7 +2138,7 @@ void CallbackFlushHandler::Invoke() viewShell->flushPendingLOKInvalidateTiles(); } -std::scoped_lock lock(m_mutex); +std::unique_lock lock(m_mutex); // Append messages for updated types, fetch them only now. enqueueUpdatedTypes();
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx|1 + desktop/source/lib/init.cxx | 19 +-- 2 files changed, 14 insertions(+), 6 deletions(-) New commits: commit f509da33f2b63be957bb4897c1bb20db1d3fc2a2 Author: Luboš Luňák AuthorDate: Fri Feb 25 12:22:16 2022 +0100 Commit: Andras Timar CommitDate: Mon Feb 28 15:03:54 2022 +0100 make sure that LOK "updated types" start a timer as well 273a25c796fca9afa0dfadac57dc3f336831221c changed the handling of LOK messages to only set up an "updated" flag for types and then when flushing the value is fetched. This means that queue() is not called for such updates, and so the timeout to flush the messages wasn't started. Change-Id: I3a7324c86a55697f509f80b6c54cb949fb1daa72 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130459 Tested-by: Jenkins CollaboraOffice Reviewed-by: Andras Timar diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index b2ba47239f2f..c19e4c5b0ac1 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -175,6 +175,7 @@ namespace desktop { typedef std::vector queue_type1; typedef std::vector queue_type2; +void startTimer(); bool removeAll(int type); bool removeAll(int type, const std::function& rTestFunc); bool removeAll(const std::function& rTestFunc); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 2ae5fc89f731..ca65ec4ae2ca 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1402,6 +1402,8 @@ void CallbackFlushHandler::setUpdatedType( int nType, bool value ) if( m_updatedTypes.size() <= o3tl::make_unsigned( nType )) m_updatedTypes.resize( nType + 1 ); // new are default-constructed, i.e. false m_updatedTypes[ nType ] = value; +if(value) +startTimer(); } void CallbackFlushHandler::resetUpdatedType( int nType ) @@ -1416,6 +1418,8 @@ void CallbackFlushHandler::setUpdatedTypePerViewId( int nType, int nViewId, int if( types.size() <= o3tl::make_unsigned( nType )) types.resize( nType + 1 ); // new are default-constructed, i.e. 'set' is false types[ nType ] = PerViewIdData{ value, nSourceViewId }; +if(value) +startTimer(); } void CallbackFlushHandler::resetUpdatedTypePerViewId( int nType, int nViewId ) @@ -1745,12 +1749,7 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData) #endif lock.unlock(); -if (!IsActive()) -{ -Start(); -} -if (!m_TimeoutIdle.IsActive()) -m_TimeoutIdle.Start(); +startTimer(); } bool CallbackFlushHandler::processInvalidateTilesEvent(int type, CallbackData& aCallbackData) @@ -2234,6 +2233,14 @@ void CallbackFlushHandler::Invoke() m_TimeoutIdle.Stop(); } +void CallbackFlushHandler::startTimer() +{ +if (!IsActive()) +Start(); +if (!m_TimeoutIdle.IsActive()) +m_TimeoutIdle.Start(); +} + bool CallbackFlushHandler::removeAll(int type) { bool bErased = false;
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx|2 + desktop/source/lib/init.cxx | 49 +++- 2 files changed, 42 insertions(+), 9 deletions(-) New commits: commit 876be07b6dd61eb323428aca6c31c3e58a8488fd Author: Michael Meeks AuthorDate: Tue Jan 18 17:04:15 2022 + Commit: Michael Meeks CommitDate: Mon Feb 7 13:09:07 2022 +0100 lok: avoid duplicate emission of statechanged: messages. We tend to get many of these per keystroke, with the same state. Change-Id: I9d759f54aee8d6dabcef094997e8f352dd608ec3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128578 Tested-by: Jenkins CollaboraOffice Reviewed-by: Ashod Nakashian diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index bb560264743b..b2ba47239f2f 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -85,6 +85,7 @@ namespace desktop { static tools::Rectangle CheckedRectangle(const tools::Rectangle& rect); }; +/// One instance of this per view, handles flushing callbacks class DESKTOP_DLLPUBLIC CallbackFlushHandler final : public Idle, public SfxLokCallbackInterface { public: @@ -190,6 +191,7 @@ namespace desktop { queue_type1 m_queue1; queue_type2 m_queue2; std::map m_states; +std::unordered_map m_lastStateChange; std::unordered_map> m_viewStates; // For some types only the last message matters (see isUpdatedType()) or only the last message diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 4693e79ec3f6..2ae5fc89f731 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1350,6 +1350,7 @@ 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), @@ -2151,22 +2152,52 @@ void CallbackFlushHandler::Invoke() const auto& payload = it2->getPayload(); const int viewId = lcl_isViewCallbackType(type) ? it2->getViewId() : -1; +SAL_INFO("lok", "processing event: [" << type << ',' << viewId << "]: [" << payload << "]."); + +// common code-path for events on this view: if (viewId == -1) { -const auto stateIt = m_states.find(type); -if (stateIt != m_states.end()) +size_t idx; +// key-value pairs +if (type == LOK_CALLBACK_STATE_CHANGED && +(idx = payload.find('=')) != std::string::npos) { -// If the state didn't change, it's safe to ignore. -if (stateIt->second == payload) +std::string key = payload.substr(0, idx); +std::string value = payload.substr(idx+1); +const auto stateIt = m_lastStateChange.find(key); +if (stateIt != m_lastStateChange.end()) { -SAL_INFO("lok", "Skipping duplicate [" << type << "]: [" << payload << "]."); -continue; +// If the value didn't change, it's safe to ignore. +if (stateIt->second == value) +{ +SAL_INFO("lok", "Skipping new state duplicate: [" << type << "]: [" << payload << "]."); +continue; +} +SAL_INFO("lok", "Replacing a state element [" << type << "]: [" << payload << "]."); +stateIt->second = value; +} +else +{ +SAL_INFO("lok", "Inserted a new state element: [" << type << "]: [" << payload << "]"); +m_lastStateChange.emplace(key, value); +} +} +else +{ +const auto stateIt = m_states.find(type); +if (stateIt != m_states.end()) +{ +// If the state didn't change, it's safe to ignore. +if (stateIt->second == payload) +{ +SAL_INFO("lok", "Skipping duplicate [" << type << "]: [" << payload << "]."); +continue; +} +stateIt->second = payload; } - -stateIt->second = payload; } } -else +else // less common path for events relating to other views { const auto statesIt = m_viewStates.find(viewId); if (statesIt != m_viewStates.end())
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx|4 +++- desktop/source/lib/init.cxx | 20 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) New commits: commit 2c8f792bf839bd712e0301f087d339ffcc1d22f3 Author: Luboš Luňák AuthorDate: Wed Dec 15 15:22:45 2021 +0100 Commit: Andras Timar CommitDate: Thu Dec 16 09:33:51 2021 +0100 ensure invalidate tiles LOK message range checking 3db1ce30ab235ad22aed71c22e4f6f52b7b88829 added some range checking on the rectangles, such as making sure (x,y) is not less than (0,0), and it added it to converting string messages back to rectangles. But then 3b729db05553c1a6d461fb41c89a05702f407448 avoided the conversions from string messages back to rectangles, and thus it avoided also these checks. Change-Id: I73a08e418dc2e48ef5e89fe1aee0272851f7d363 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126864 Tested-by: Jenkins CollaboraOffice Reviewed-by: Ashod Nakashian diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 5e1e23b2cdb5..bb560264743b 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -52,7 +52,7 @@ namespace desktop { } RectangleAndPart(const tools::Rectangle* pRect, int nPart) -: m_aRectangle( pRect ? *pRect : emptyAllRectangle) +: m_aRectangle( pRect ? CheckedRectangle(*pRect) : emptyAllRectangle) , m_nPart(nPart) { } @@ -81,6 +81,8 @@ namespace desktop { } static RectangleAndPart Create(const std::string& rPayload); +static tools::Rectangle CheckedRectangle(tools::Long nLeft, tools::Long nTop, tools::Long nWidth, tools::Long nHeight); +static tools::Rectangle CheckedRectangle(const tools::Rectangle& rect); }; class DESKTOP_DLLPUBLIC CallbackFlushHandler final : public Idle, public SfxLokCallbackInterface diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index bf4bd7883f4f..22523ecc2227 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -555,6 +555,13 @@ RectangleAndPart RectangleAndPart::Create(const std::string& rPayload) nPart = rtl_str_toInt64_WithLength(pos, 10, end - pos); } +aRet.m_aRectangle = CheckedRectangle(nLeft, nTop, nWidth, nHeight); +aRet.m_nPart = nPart; +return aRet; +} + +tools::Rectangle RectangleAndPart::CheckedRectangle(tools::Long nLeft, tools::Long nTop, tools::Long nWidth, tools::Long nHeight) +{ if (nWidth > 0 && nHeight > 0) { // The top-left corner starts at (0, 0). @@ -572,14 +579,15 @@ RectangleAndPart RectangleAndPart::Create(const std::string& rPayload) } if (nWidth > 0 && nHeight > 0) -{ -aRet.m_aRectangle = tools::Rectangle(nLeft, nTop, nLeft + nWidth, nTop + nHeight); -} +return tools::Rectangle(nLeft, nTop, nLeft + nWidth, nTop + nHeight); } -// else leave empty rect. +// Else set empty rect. +return tools::Rectangle(); +} -aRet.m_nPart = nPart; -return aRet; +tools::Rectangle RectangleAndPart::CheckedRectangle(const tools::Rectangle& rect) +{ +return CheckedRectangle(rect.Left(), rect.Top(), rect.getWidth(), rect.getHeight()); } const std::string& CallbackFlushHandler::CallbackData::getPayload() const
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx|2 +- desktop/source/lib/init.cxx |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) New commits: commit 1fe6e08a1bba3a1b981218bbc485c8fa162ba162 Author: Luboš Luňák AuthorDate: Mon Oct 25 21:13:42 2021 +0200 Commit: Andras Timar CommitDate: Thu Dec 9 13:24:46 2021 +0100 make sure vector elements are initialized properly Change-Id: If18268a26118ea587f474c21b7ca0f1fa4622744 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126442 Tested-by: Jenkins CollaboraOffice Reviewed-by: Andras Timar diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 3f3802d17d4e..4499914839a0 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -197,7 +197,7 @@ namespace desktop { std::vector m_updatedTypes; // index is type, value is if set struct PerViewIdData { -bool set; // value is if set +bool set = false; // value is if set int sourceViewId; }; // Flat_map is used in preference to unordered_map because the map is accessed very often. diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 16ffe6f097e7..3bd212195f4d 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1505,7 +1505,7 @@ void CallbackFlushHandler::setUpdatedTypePerViewId( int nType, int nViewId, int assert(isUpdatedTypePerViewId(nType)); std::vector& types = m_updatedTypesPerViewId[ nViewId ]; if( types.size() <= o3tl::make_unsigned( nType )) -types.resize( nType + 1 ); // new are default-constructed, i.e. false +types.resize( nType + 1 ); // new are default-constructed, i.e. 'set' is false types[ nType ] = PerViewIdData{ value, nSourceViewId }; }
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx|4 +++- desktop/source/lib/init.cxx |2 +- 2 files changed, 4 insertions(+), 2 deletions(-) New commits: commit 6af4b4c8dcfde5c8e258fc356cbe2d6cf94490c8 Author: Luboš Luňák AuthorDate: Mon Oct 25 22:48:28 2021 +0200 Commit: Luboš Luňák CommitDate: Tue Oct 26 20:34:12 2021 +0200 use boost flat_map for faster map setUpdatedTypePerViewId() gets called so often that even unordered_map lookup and allocations show up in profiling. It seems that flat_map can do better. Change-Id: Id2e4f0c40d6973b51e557f84a08bf12feb58b3ce Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124191 Tested-by: Jenkins CollaboraOffice Reviewed-by: Luboš Luňák diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 2035226bc059..3f3802d17d4e 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -199,7 +200,8 @@ namespace desktop { bool set; // value is if set int sourceViewId; }; -std::unordered_map> m_updatedTypesPerViewId; // key is view, index is type +// Flat_map is used in preference to unordered_map because the map is accessed very often. +boost::container::flat_map> m_updatedTypesPerViewId; // key is view, index is type LibreOfficeKitDocument* m_pDocument; int m_viewId = -1; // view id of the associated SfxViewShell diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 20916a4ebd3b..a8517c3cbaba 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -2144,7 +2144,7 @@ void CallbackFlushHandler::enqueueUpdatedTypes() // First move data to local structures, so that callbacks don't possibly modify it. std::vector updatedTypes; std::swap(updatedTypes, m_updatedTypes); -std::unordered_map> updatedTypesPerViewId; +boost::container::flat_map> updatedTypesPerViewId; std::swap(updatedTypesPerViewId, m_updatedTypesPerViewId); // Some types must always precede other types, for example
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source include/editeng include/sfx2 include/test sc/qa sd/qa sfx2/source sw/inc sw/qa sw/source test/source
desktop/inc/lib/init.hxx | 23 +++ desktop/source/lib/init.cxx| 148 + include/editeng/outliner.hxx |2 include/sfx2/lokcallback.hxx | 11 + include/sfx2/lokhelper.hxx | 18 ++- include/sfx2/viewsh.hxx|5 include/test/lokcallback.hxx | 24 +++- sc/qa/unit/tiledrendering/tiledrendering.cxx | 15 ++ sd/qa/unit/tiledrendering/tiledrendering.cxx | 15 ++ sfx2/source/view/lokhelper.cxx | 69 +-- sfx2/source/view/viewsh.cxx| 33 + sw/inc/view.hxx|1 sw/inc/viscrs.hxx |3 sw/qa/core/txtnode/txtnode.cxx |2 sw/qa/extras/tiledrendering/tiledrendering.cxx | 72 sw/source/core/crsr/viscrs.cxx | 85 +- sw/source/uibase/inc/wrtsh.hxx |2 sw/source/uibase/uiview/view.cxx |7 + sw/source/uibase/wrtsh/wrtsh4.cxx | 13 ++ test/source/lokcallback.cxx| 121 +++- 20 files changed, 588 insertions(+), 81 deletions(-) New commits: commit d18d53da7cd554ed887ae53f5fb7c6ac1f7e4a98 Author: Luboš Luňák AuthorDate: Fri Oct 15 08:43:23 2021 +0200 Commit: Luboš Luňák CommitDate: Sun Oct 24 01:41:00 2021 +0200 change some LOK internal updates to be pull model instead of push Some LOK messages may get called very often, such as updates about cursor position. And since only the last one matters, they get generated every time, which costs some time, and then later except for one they get all discard again from CallbackFlushHandler queue, which again costs time. Change the model to instead only set an 'updated' flag, and CallbackFlushHandler will request the actual message payload only before flushing. This commit changes LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR and LOK_CALLBACK_INVALIDATE_VIEW_CURSOR to work this way. Change-Id: I376be63176c0b4b5cb492fbf529c21ed01b35481 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124084 Tested-by: Jenkins CollaboraOffice Reviewed-by: Luboš Luňák diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index c43e82fdd430..2035226bc059 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -103,6 +103,8 @@ namespace desktop { virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) override; virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, int nViewId) override; virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart) override; +virtual void libreOfficeKitViewUpdatedCallback(int nType) override; +virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) override; private: struct CallbackData @@ -171,6 +173,8 @@ namespace desktop { queue_type2::iterator toQueue2(queue_type1::iterator); queue_type2::reverse_iterator toQueue2(queue_type1::reverse_iterator); void queue(const int type, CallbackData& data); +void enqueueUpdatedTypes(); +void enqueueUpdatedType( int type, SfxViewShell* sourceViewShell, int viewId ); /** 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. */ @@ -178,6 +182,25 @@ namespace desktop { queue_type2 m_queue2; std::map m_states; std::unordered_map> m_viewStates; + +// For some types only the last message matters (see isUpdatedType()) or only the last message +// per each viewId value matters (see isUpdatedTypePerViewId()), so instead of using push model +// where we'd get flooded by repeated messages (which might be costly to generate and process), +// the preferred way is that libreOfficeKitViewUpdatedCallback() +// or libreOfficeKitViewUpdatedCallbackPerViewId() get called to notify about such a message being +// needed, and we'll set a flag here to fetch the actual message before flushing. +void setUpdatedType( int nType, bool value ); +void setUpdatedTypePerViewId( int nType, int nViewId, int nSourceViewId, bool value ); +void resetUpdatedType( int nType); +void resetUpdatedTypePerViewId( int nType, int nViewId ); +std::vector m_updatedTypes; // index is type, value is if set +struct PerViewIdData +{ +bool set; // value is if set +int sourceViewId; +}; +std::unordered_map> m_updatedTypesPerViewId; // key is view, index is type +
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx|9 + desktop/source/lib/init.cxx | 26 ++ 2 files changed, 31 insertions(+), 4 deletions(-) New commits: commit 3f6f1a45c1f4225817188f97721e6546e38871e2 Author: Luboš Luňák AuthorDate: Fri Sep 24 00:11:04 2021 +0200 Commit: Luboš Luňák CommitDate: Tue Sep 28 14:01:25 2021 +0200 add extra timeout with higher priority to LOK flushing The normal idle has TaskPriority::POST_PAINT, which means that if we get too busy, the idle won't be called for a long time, meaning the queue will get longer and longer, making its processing slower, and client interactivity will be very poor, with updates possibly coming only when everything becomes idle. The second timeout will flush the queue after a reasonable timeout. I don't think there's an optimal value, so let's choose 100ms for now. Change-Id: Ia1312a690aefd2c8628c82e0f42b2993802d8b1e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122737 Tested-by: Luboš Luňák Reviewed-by: Luboš Luňák diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 6cbabd3b..eee6b0fb4d76 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -146,6 +146,15 @@ namespace desktop { void *m_pData; int m_nDisableCallbacks; std::mutex m_mutex; +class TimeoutIdle : public Timer +{ +public: +TimeoutIdle( CallbackFlushHandler* handler ); +virtual void Invoke() override; +private: +CallbackFlushHandler* mHandler; +}; +TimeoutIdle m_TimeoutIdle; }; struct DESKTOP_DLLPUBLIC LibLODocument_Impl : public _LibreOfficeKitDocument diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 824f45b5d23f..3e09f2d8b5ab 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1392,12 +1392,28 @@ 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(); +} + CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, LibreOfficeKitCallback pCallback, void* pData) -: Idle( "lokit timer callback" ), +: Idle( "lokit idle callback" ), m_pDocument(pDocument), m_pCallback(pCallback), m_pData(pData), - m_nDisableCallbacks(0) + m_nDisableCallbacks(0), + m_TimeoutIdle( this ) { SetPriority(TaskPriority::POST_PAINT); @@ -1414,8 +1430,6 @@ CallbackFlushHandler::CallbackFlushHandler(LibreOfficeKitDocument* pDocument, Li m_states.emplace(LOK_CALLBACK_CURSOR_VISIBLE, "NIL"); m_states.emplace(LOK_CALLBACK_SET_PART, "NIL"); m_states.emplace(LOK_CALLBACK_TABLE_SELECTED, "NIL"); - -Start(); } CallbackFlushHandler::~CallbackFlushHandler() @@ -1696,6 +1710,8 @@ void CallbackFlushHandler::queue(const int type, const char* data) { Start(); } +if (!m_TimeoutIdle.IsActive()) +m_TimeoutIdle.Start(); } bool CallbackFlushHandler::processInvalidateTilesEvent(int type, CallbackData& aCallbackData) @@ -2059,6 +2075,8 @@ void CallbackFlushHandler::Invoke() m_queue1.clear(); m_queue2.clear(); +Stop(); +m_TimeoutIdle.Stop(); } bool CallbackFlushHandler::removeAll(int type)
[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - desktop/inc desktop/source
desktop/inc/lib/init.hxx| 23 ++--- desktop/source/lib/init.cxx | 192 +--- 2 files changed, 123 insertions(+), 92 deletions(-) New commits: commit 475d6528a5ae1781c5b09cbcd3fd305c4180c168 Author: Noel Grandin AuthorDate: Wed Aug 4 13:01:22 2021 +0200 Commit: Luboš Luňák CommitDate: Thu Sep 23 00:09:00 2021 +0200 speed up scanning the LOK queue we frequently scan the queue to caolesce events. Most of the time we are scanning based on the event type. So split the queue data into a compact queue that only contains the type, and another queue for the rest of the data. That makes the scanning __much__ more cache-friendly. Change-Id: I92d0b95611cd139cac8532f9297eaabda71d5fe9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119996 Tested-by: Jenkins CollaboraOffice Reviewed-by: Noel Grandin (cherry picked from commit acf9cf33d53e4bf598ddbdab102bfbd6bb14f8a3) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121558 Tested-by: Jenkins (cherry picked from commit 3b3e4ee97af23f210fa39f1af3ddf1de63291371) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122434 Reviewed-by: Luboš Luňák diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 3d95d4f602b4..ed35ebc2fa13 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -92,9 +92,8 @@ namespace desktop { struct CallbackData { -CallbackData(int type, const std::string& payload) -: Type(type) -, PayloadString(payload) +CallbackData(const std::string& payload) +: PayloadString(payload) { } @@ -117,7 +116,6 @@ namespace desktop { /// Returns true iff there is cached data. bool isCached() const { return PayloadObject.which() != 0; } -int Type; std::string PayloadString; private: @@ -125,14 +123,19 @@ namespace desktop { boost::variant PayloadObject; }; -typedef std::vector queue_type; +typedef std::vector queue_type1; +typedef std::vector queue_type2; private: -bool removeAll(const std::function& rTestFunc); -bool processInvalidateTilesEvent(CallbackData& aCallbackData); -bool processWindowEvent(CallbackData& aCallbackData); - -queue_type m_queue; +bool removeAll(const std::function& rTestFunc); +bool processInvalidateTilesEvent(int type, CallbackData& aCallbackData); +bool processWindowEvent(int type, CallbackData& aCallbackData); +queue_type2::reverse_iterator toQueue2(queue_type1::reverse_iterator); + +/** 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; +queue_type2 m_queue2; std::map m_states; std::unordered_map> m_viewStates; LibreOfficeKitDocument* m_pDocument; diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index c95de6ed4082..86c468df402f 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1438,13 +1438,19 @@ void CallbackFlushHandler::callback(const int type, const char* payload, void* d } } +CallbackFlushHandler::queue_type2::reverse_iterator CallbackFlushHandler::toQueue2(CallbackFlushHandler::queue_type1::reverse_iterator pos) +{ +int delta = std::distance(m_queue1.rbegin(), pos); +return m_queue2.rbegin() + delta; +} + void CallbackFlushHandler::queue(const int type, const char* data) { comphelper::ProfileZone aZone("CallbackFlushHandler::queue"); -CallbackData aCallbackData(type, (data ? data : "(nil)")); +CallbackData aCallbackData(data ? data : "(nil)"); const std::string& payload = aCallbackData.PayloadString; -SAL_INFO("lok", "Queue: [" << type << "]: [" << payload << "] on " << m_queue.size() << " entries."); +SAL_INFO("lok", "Queue: [" << type << "]: [" << payload << "] on " << m_queue1.size() << " entries."); bool bIsChartActive = false; if (type == LOK_CALLBACK_GRAPHIC_SELECTION) @@ -1523,10 +1529,10 @@ void CallbackFlushHandler::queue(const int type, const char* data) case LOK_CALLBACK_CALC_FUNCTION_LIST: case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY: { -const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(), -[type] (const queue_type::value_type& elem) { return (elem.Type == type); }); - -if (pos != m_queue.rend() && pos->PayloadString == payload) +const auto& pos = std::find_if(m_queue1.rbegin(), m_queue1.rend(), +[type] (int elemType) { return (elemType == type); }); +auto pos2 = toQueue2(pos); +if (pos !=