summaryrefslogtreecommitdiff
path: root/desktop/source
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2021-10-15 08:43:23 +0200
committerLuboš Luňák <l.lunak@collabora.com>2021-10-24 01:40:45 +0200
commit273a25c796fca9afa0dfadac57dc3f336831221c (patch)
tree3efb1e505e27164bcdb2c164c59a48c814221ffe /desktop/source
parent667c2499d861cfcd26935fc0512cb5aaf602c4c5 (diff)
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/+/124083 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'desktop/source')
-rw-r--r--desktop/source/lib/init.cxx144
1 files changed, 144 insertions, 0 deletions
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index ba3315306464..c38a6dd8d754 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -698,6 +698,23 @@ static bool lcl_isViewCallbackType(const int type)
}
}
+static bool isUpdatedType(int /*type*/)
+{
+ return false;
+}
+
+static bool isUpdatedTypePerViewId(int type)
+{
+ switch (type)
+ {
+ case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
+ case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
+ return true;
+ default:
+ return false;
+ }
+}
+
static int lcl_getViewId(const std::string& payload)
{
// this is a cheap way how to get the viewId from a JSON message; proper
@@ -1455,6 +1472,48 @@ CallbackFlushHandler::queue_type2::reverse_iterator CallbackFlushHandler::toQueu
return m_queue2.rbegin() + delta;
}
+void CallbackFlushHandler::setUpdatedType( int nType, bool value )
+{
+ assert(isUpdatedType(nType));
+ if( m_updatedTypes.size() <= o3tl::make_unsigned( nType ))
+ m_updatedTypes.resize( nType + 1 ); // new are default-constructed, i.e. false
+ m_updatedTypes[ nType ] = value;
+}
+
+void CallbackFlushHandler::resetUpdatedType( int nType )
+{
+ setUpdatedType( nType, false );
+}
+
+void CallbackFlushHandler::setUpdatedTypePerViewId( int nType, int nViewId, int nSourceViewId, bool value )
+{
+ assert(isUpdatedTypePerViewId(nType));
+ std::vector<PerViewIdData>& types = m_updatedTypesPerViewId[ nViewId ];
+ if( types.size() <= o3tl::make_unsigned( nType ))
+ types.resize( nType + 1 ); // new are default-constructed, i.e. false
+ types[ nType ] = PerViewIdData{ value, nSourceViewId };
+}
+
+void CallbackFlushHandler::resetUpdatedTypePerViewId( int nType, int nViewId )
+{
+ assert(isUpdatedTypePerViewId(nType));
+ bool allViewIds = false;
+ // Handle specially messages that do not have viewId for backwards compatibility.
+ if( nType == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR && !comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation())
+ allViewIds = true;
+ if( !allViewIds )
+ {
+ setUpdatedTypePerViewId( nType, nViewId, -1, false );
+ return;
+ }
+ for( auto& it : m_updatedTypesPerViewId )
+ {
+ std::vector<PerViewIdData>& types = it.second;
+ if( types.size() >= o3tl::make_unsigned( nType ))
+ types[ nType ].set = false;
+ }
+}
+
void CallbackFlushHandler::libreOfficeKitViewCallback(int nType, const char* pPayload)
{
CallbackData callbackData(pPayload);
@@ -1473,6 +1532,22 @@ void CallbackFlushHandler::libreOfficeKitViewInvalidateTilesCallback(const tools
queue(LOK_CALLBACK_INVALIDATE_TILES, callbackData);
}
+void CallbackFlushHandler::libreOfficeKitViewUpdatedCallback(int nType)
+{
+ assert(isUpdatedType( nType ));
+ std::unique_lock<std::mutex> lock(m_mutex);
+ SAL_INFO("lok", "Updated: [" << nType << "]");
+ setUpdatedType(nType, true);
+}
+
+void CallbackFlushHandler::libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId)
+{
+ assert(isUpdatedTypePerViewId( nType ));
+ std::unique_lock<std::mutex> lock(m_mutex);
+ SAL_INFO("lok", "Updated: [" << nType << "]");
+ setUpdatedTypePerViewId(nType, nViewId, nSourceViewId, true);
+}
+
void CallbackFlushHandler::queue(const int type, const char* data)
{
CallbackData callbackData(data);
@@ -1536,6 +1611,20 @@ void CallbackFlushHandler::queue(const int type, CallbackData& aCallbackData)
std::unique_lock<std::mutex> 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.
+ // Reset the updated flag if we get a normal message.
+ if(isUpdatedType(type))
+ {
+ SAL_INFO("lok", "Received event with updated type [" << type << "] as normal callback");
+ resetUpdatedType(type);
+ }
+ if(isUpdatedTypePerViewId(type))
+ {
+ SAL_INFO("lok", "Received event with updated type [" << type << "] as normal callback");
+ resetUpdatedTypePerViewId(type, aCallbackData.getViewId());
+ }
+
// drop duplicate callbacks for the listed types
switch (type)
{
@@ -2028,6 +2117,58 @@ bool CallbackFlushHandler::processWindowEvent(int type, CallbackData& aCallbackD
return false;
}
+void CallbackFlushHandler::enqueueUpdatedTypes()
+{
+ if( m_updatedTypes.empty() && m_updatedTypesPerViewId.empty())
+ return;
+ SfxViewShell* viewShell = SfxViewShell::GetFirst( false,
+ [this](const SfxViewShell* shell) { return shell->GetViewShellId().get() == m_viewId; } );
+ assert(viewShell != nullptr);
+ for( size_t type = 0; type < m_updatedTypes.size(); ++type )
+ {
+ if(m_updatedTypes[ type ])
+ {
+ assert(isUpdatedType( type ));
+ enqueueUpdatedType( type, viewShell, m_viewId );
+ }
+ }
+ for( const auto& it : m_updatedTypesPerViewId )
+ {
+ int viewId = it.first;
+ const std::vector<PerViewIdData>& types = it.second;
+ for( size_t type = 0; type < types.size(); ++type )
+ {
+ if(types[ type ].set)
+ {
+ assert(isUpdatedTypePerViewId( type ));
+ SfxViewShell* sourceViewShell = viewShell;
+ const int sourceViewId = types[ type ].sourceViewId;
+ if( sourceViewId != m_viewId )
+ sourceViewShell = SfxViewShell::GetFirst( false,
+ [sourceViewId](const SfxViewShell* shell) { return shell->GetViewShellId().get() == sourceViewId; } );
+ if(sourceViewShell == nullptr)
+ {
+ SAL_INFO("lok", "View #" << sourceViewId << " no longer found for updated event [" << type << "]");
+ continue; // View removed, probably cleaning up.
+ }
+ enqueueUpdatedType( type, sourceViewShell, viewId );
+ }
+ }
+ }
+ m_updatedTypes.clear();
+ m_updatedTypesPerViewId.clear();
+}
+
+void CallbackFlushHandler::enqueueUpdatedType( int type, SfxViewShell* viewShell, int viewId )
+{
+ OString payload = viewShell->getLOKPayload( type, viewId );
+ CallbackData callbackData(payload.getStr(), viewId);
+ m_queue1.emplace_back(type);
+ m_queue2.emplace_back(callbackData);
+ SAL_INFO("lok", "Queued updated [" << type << "]: [" << callbackData.getPayload()
+ << "] to have " << m_queue1.size() << " entries.");
+}
+
void CallbackFlushHandler::Invoke()
{
comphelper::ProfileZone aZone("CallbackFlushHandler::Invoke");
@@ -2045,6 +2186,9 @@ void CallbackFlushHandler::Invoke()
std::scoped_lock<std::mutex> lock(m_mutex);
+ // Append messages for updated types, fetch them only now.
+ enqueueUpdatedTypes();
+
SAL_INFO("lok", "Flushing " << m_queue1.size() << " elements.");
auto it1 = m_queue1.begin();
auto it2 = m_queue2.begin();