common/MessageQueue.cpp | 342 +++++++++++++++++++++++++----------------------- 1 file changed, 184 insertions(+), 158 deletions(-)
New commits: commit 39d34cbab4715ba10d5bab10c82746cb4605baca Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> AuthorDate: Tue Jun 2 23:16:47 2020 -0400 Commit: Ashod Nakashian <ashnak...@gmail.com> CommitDate: Thu Jul 2 21:49:31 2020 +0200 wsd: match LOK callback type as integer String comparisons are costly and much less readable. Now we have a fast switch with LOK_CALLBACK enum values. Change-Id: Icc24b91b174cd9bbb7e0d64039df080c0a4338f2 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/96375 Tested-by: Jenkins Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/common/MessageQueue.cpp b/common/MessageQueue.cpp index 064a27717..f239a2e9c 100644 --- a/common/MessageQueue.cpp +++ b/common/MessageQueue.cpp @@ -192,207 +192,233 @@ std::string TileQueue::removeCallbackDuplicate(const std::string& callbackMsg) return std::string(); // the message is "callback <view> <id> ..." - const std::string& callbackType = tokens[2]; - - // FIXME: Good grief, why don't we use the symbolic LOK_CALLBACK_FOO names here? Doing it this - // way is somewhat fragile and certainly bad style. - if (callbackType == "0") // invalidation - { - int msgX, msgY, msgW, msgH, msgPart; - - if (!extractRectangle(tokens, msgX, msgY, msgW, msgH, msgPart)) - return std::string(); + const auto pair = Util::i32FromString(tokens[2]); + if (!pair.second) + return std::string(); - bool performedMerge = false; + const auto callbackType = static_cast<LibreOfficeKitCallbackType>(pair.first); - // we always travel the entire queue - size_t i = 0; - while (i < getQueue().size()) + switch (callbackType) + { + case LOK_CALLBACK_INVALIDATE_TILES: // invalidation { - auto& it = getQueue()[i]; + int msgX, msgY, msgW, msgH, msgPart; - StringVector queuedTokens = Util::tokenize(it.data(), it.size()); - if (queuedTokens.size() < 3) - { - ++i; - continue; - } - - // not a invalidation callback - if (queuedTokens[0] != tokens[0] || queuedTokens[1] != tokens[1] || queuedTokens[2] != tokens[2]) - { - ++i; - continue; - } + if (!extractRectangle(tokens, msgX, msgY, msgW, msgH, msgPart)) + return std::string(); - int queuedX, queuedY, queuedW, queuedH, queuedPart; + bool performedMerge = false; - if (!extractRectangle(queuedTokens, queuedX, queuedY, queuedW, queuedH, queuedPart)) + // we always travel the entire queue + std::size_t i = 0; + while (i < getQueue().size()) { - ++i; - continue; - } + auto& it = getQueue()[i]; - if (msgPart != queuedPart) - { - ++i; - continue; - } + StringVector queuedTokens = Util::tokenize(it.data(), it.size()); + if (queuedTokens.size() < 3) + { + ++i; + continue; + } - // the invalidation in the queue is fully covered by the message, - // just remove it - if (msgX <= queuedX && queuedX + queuedW <= msgX + msgW && msgY <= queuedY && queuedY + queuedH <= msgY + msgH) - { - LOG_TRC("Removing smaller invalidation: " - << std::string(it.data(), it.size()) << " -> " << tokens[0] << ' ' - << tokens[1] << ' ' << tokens[2] << ' ' << msgX << ' ' << msgY << ' ' - << msgW << ' ' << msgH << ' ' << msgPart); - - // remove from the queue - getQueue().erase(getQueue().begin() + i); - continue; - } + // not a invalidation callback + if (queuedTokens[0] != tokens[0] || queuedTokens[1] != tokens[1] + || queuedTokens[2] != tokens[2]) + { + ++i; + continue; + } - // the invalidation just intersects, join those (if the result is - // small) - if (TileDesc::rectanglesIntersect(msgX, msgY, msgW, msgH, queuedX, queuedY, queuedW, queuedH)) - { - int joinX = std::min(msgX, queuedX); - int joinY = std::min(msgY, queuedY); - int joinW = std::max(msgX + msgW, queuedX + queuedW) - joinX; - int joinH = std::max(msgY + msgH, queuedY + queuedH) - joinY; - - const int reasonableSizeX = 4*3840; // 4x tile at 100% zoom - const int reasonableSizeY = 2*3840; // 2x tile at 100% zoom - if (joinW > reasonableSizeX || joinH > reasonableSizeY) + int queuedX, queuedY, queuedW, queuedH, queuedPart; + + if (!extractRectangle(queuedTokens, queuedX, queuedY, queuedW, queuedH, queuedPart)) { ++i; continue; } - LOG_TRC("Merging invalidations: " - << std::string(it.data(), it.size()) << " and " << tokens[0] << ' ' - << tokens[1] << ' ' << tokens[2] << ' ' << msgX << ' ' << msgY << ' ' - << msgW << ' ' << msgH << ' ' << msgPart << " -> " << tokens[0] << ' ' - << tokens[1] << ' ' << tokens[2] << ' ' << joinX << ' ' << joinY << ' ' - << joinW << ' ' << joinH << ' ' << msgPart); - - msgX = joinX; - msgY = joinY; - msgW = joinW; - msgH = joinH; - performedMerge = true; - - // remove from the queue - getQueue().erase(getQueue().begin() + i); - continue; - } + if (msgPart != queuedPart) + { + ++i; + continue; + } - ++i; - } + // the invalidation in the queue is fully covered by the message, + // just remove it + if (msgX <= queuedX && queuedX + queuedW <= msgX + msgW && msgY <= queuedY + && queuedY + queuedH <= msgY + msgH) + { + LOG_TRC("Removing smaller invalidation: " + << std::string(it.data(), it.size()) << " -> " << tokens[0] << ' ' + << tokens[1] << ' ' << tokens[2] << ' ' << msgX << ' ' << msgY << ' ' + << msgW << ' ' << msgH << ' ' << msgPart); - if (performedMerge) - { - size_t pre = tokens[0].size() + tokens[1].size() + tokens[2].size() + 3; - size_t post = pre + tokens[3].size() + tokens[4].size() + tokens[5].size() + tokens[6].size() + 4; + // remove from the queue + getQueue().erase(getQueue().begin() + i); + continue; + } - std::string result = callbackMsg.substr(0, pre) + - std::to_string(msgX) + ", " + - std::to_string(msgY) + ", " + - std::to_string(msgW) + ", " + - std::to_string(msgH) + ", " + callbackMsg.substr(post); + // the invalidation just intersects, join those (if the result is + // small) + if (TileDesc::rectanglesIntersect(msgX, msgY, msgW, msgH, queuedX, queuedY, queuedW, + queuedH)) + { + int joinX = std::min(msgX, queuedX); + int joinY = std::min(msgY, queuedY); + int joinW = std::max(msgX + msgW, queuedX + queuedW) - joinX; + int joinH = std::max(msgY + msgH, queuedY + queuedH) - joinY; + + const int reasonableSizeX = 4 * 3840; // 4x tile at 100% zoom + const int reasonableSizeY = 2 * 3840; // 2x tile at 100% zoom + if (joinW > reasonableSizeX || joinH > reasonableSizeY) + { + ++i; + continue; + } - LOG_TRC("Merge result: " << result); + LOG_TRC("Merging invalidations: " + << std::string(it.data(), it.size()) << " and " << tokens[0] << ' ' + << tokens[1] << ' ' << tokens[2] << ' ' << msgX << ' ' << msgY << ' ' + << msgW << ' ' << msgH << ' ' << msgPart << " -> " << tokens[0] << ' ' + << tokens[1] << ' ' << tokens[2] << ' ' << joinX << ' ' << joinY << ' ' + << joinW << ' ' << joinH << ' ' << msgPart); - return result; - } - } - else if (callbackType == "8") // state changed - { - if (tokens.size() < 4) - return std::string(); + msgX = joinX; + msgY = joinY; + msgW = joinW; + msgH = joinH; + performedMerge = true; - std::string unoCommand = extractUnoCommand(tokens[3]); - if (unoCommand.empty()) - return std::string(); + // remove from the queue + getQueue().erase(getQueue().begin() + i); + continue; + } - // remove obsolete states of the same .uno: command - for (size_t i = 0; i < getQueue().size(); ++i) - { - auto& it = getQueue()[i]; + ++i; + } - StringVector queuedTokens = Util::tokenize(it.data(), it.size()); - if (queuedTokens.size() < 4) - continue; + if (performedMerge) + { + std::size_t pre = tokens[0].size() + tokens[1].size() + tokens[2].size() + 3; + std::size_t post = pre + tokens[3].size() + tokens[4].size() + tokens[5].size() + + tokens[6].size() + 4; - if (queuedTokens[0] != tokens[0] || queuedTokens[1] != tokens[1] || queuedTokens[2] != tokens[2]) - continue; + std::string result = callbackMsg.substr(0, pre) + std::to_string(msgX) + ", " + + std::to_string(msgY) + ", " + std::to_string(msgW) + ", " + + std::to_string(msgH) + ", " + callbackMsg.substr(post); - // callback, the same target, state changed; now check it's - // the same .uno: command - std::string queuedUnoCommand = extractUnoCommand(queuedTokens[3]); - if (queuedUnoCommand.empty()) - continue; + LOG_TRC("Merge result: " << result); - if (unoCommand == queuedUnoCommand) - { - LOG_TRC("Remove obsolete uno command: " << std::string(it.data(), it.size()) << " -> " << LOOLProtocol::getAbbreviatedMessage(callbackMsg)); - getQueue().erase(getQueue().begin() + i); - break; + return result; } } - } - else if (callbackType == "1" || // the cursor has moved - callbackType == "5" || // the cursor visibility has changed - callbackType == "10" || // setting the indicator value - callbackType == "13" || // setting the document size - callbackType == "17" || // the cell cursor has moved - callbackType == "24" || // the view cursor has moved - callbackType == "26" || // the view cell cursor has moved - callbackType == "28") // the view cursor visibility has changed - { - const bool isViewCallback = (callbackType == "24" || callbackType == "26" || callbackType == "28"); + break; - std::string viewId; - if (isViewCallback) + case LOK_CALLBACK_STATE_CHANGED: // state changed { - viewId = extractViewId(callbackMsg, tokens); - } + if (tokens.size() < 4) + return std::string(); - for (size_t i = 0; i < getQueue().size(); ++i) - { - const auto& it = getQueue()[i]; + std::string unoCommand = extractUnoCommand(tokens[3]); + if (unoCommand.empty()) + return std::string(); - // skip non-callbacks quickly - if (!LOOLProtocol::matchPrefix("callback", it)) - continue; + // remove obsolete states of the same .uno: command + for (std::size_t i = 0; i < getQueue().size(); ++i) + { + auto& it = getQueue()[i]; - StringVector queuedTokens = Util::tokenize(it.data(), it.size()); - if (queuedTokens.size() < 3) - continue; + StringVector queuedTokens = Util::tokenize(it.data(), it.size()); + if (queuedTokens.size() < 4) + continue; - if (!isViewCallback && (queuedTokens.equals(1, tokens, 1) && queuedTokens.equals(2, tokens, 2))) - { - LOG_TRC("Remove obsolete callback: " << std::string(it.data(), it.size()) << " -> " << LOOLProtocol::getAbbreviatedMessage(callbackMsg)); - getQueue().erase(getQueue().begin() + i); - break; + if (queuedTokens[0] != tokens[0] || queuedTokens[1] != tokens[1] + || queuedTokens[2] != tokens[2]) + continue; + + // callback, the same target, state changed; now check it's + // the same .uno: command + std::string queuedUnoCommand = extractUnoCommand(queuedTokens[3]); + if (queuedUnoCommand.empty()) + continue; + + if (unoCommand == queuedUnoCommand) + { + LOG_TRC("Remove obsolete uno command: " + << std::string(it.data(), it.size()) << " -> " + << LOOLProtocol::getAbbreviatedMessage(callbackMsg)); + getQueue().erase(getQueue().begin() + i); + break; + } } - else if (isViewCallback && (queuedTokens.equals(1, tokens, 1) && queuedTokens.equals(2, tokens, 2))) + } + break; + + case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: // the cursor has moved + case LOK_CALLBACK_CURSOR_VISIBLE: // the cursor visibility has changed + case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE: // setting the indicator value + case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED: // setting the document size + case LOK_CALLBACK_CELL_CURSOR: // the cell cursor has moved + case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR: // the view cursor has moved + case LOK_CALLBACK_CELL_VIEW_CURSOR: // the view cell cursor has moved + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: // the view cursor visibility has changed + { + const bool isViewCallback = (callbackType == LOK_CALLBACK_INVALIDATE_VIEW_CURSOR + || callbackType == LOK_CALLBACK_CELL_VIEW_CURSOR + || callbackType == LOK_CALLBACK_VIEW_CURSOR_VISIBLE); + + const std::string viewId + = (isViewCallback ? extractViewId(callbackMsg, tokens) : std::string()); + + for (std::size_t i = 0; i < getQueue().size(); ++i) { - // we additionally need to ensure that the payload is about - // the same viewid (otherwise we'd merge them all views into - // one) - const std::string queuedViewId = extractViewId(std::string(it.data(), it.size()), queuedTokens); + const auto& it = getQueue()[i]; + + // skip non-callbacks quickly + if (!LOOLProtocol::matchPrefix("callback", it)) + continue; + + StringVector queuedTokens = Util::tokenize(it.data(), it.size()); + if (queuedTokens.size() < 3) + continue; - if (viewId == queuedViewId) + if (!isViewCallback + && (queuedTokens.equals(1, tokens, 1) && queuedTokens.equals(2, tokens, 2))) { - LOG_TRC("Remove obsolete view callback: " << std::string(it.data(), it.size()) << " -> " << LOOLProtocol::getAbbreviatedMessage(callbackMsg)); + LOG_TRC("Remove obsolete callback: " + << std::string(it.data(), it.size()) << " -> " + << LOOLProtocol::getAbbreviatedMessage(callbackMsg)); getQueue().erase(getQueue().begin() + i); break; } + else if (isViewCallback + && (queuedTokens.equals(1, tokens, 1) + && queuedTokens.equals(2, tokens, 2))) + { + // we additionally need to ensure that the payload is about + // the same viewid (otherwise we'd merge them all views into + // one) + const std::string queuedViewId + = extractViewId(std::string(it.data(), it.size()), queuedTokens); + + if (viewId == queuedViewId) + { + LOG_TRC("Remove obsolete view callback: " + << std::string(it.data(), it.size()) << " -> " + << LOOLProtocol::getAbbreviatedMessage(callbackMsg)); + getQueue().erase(getQueue().begin() + i); + break; + } + } } } - } + break; + + default: + break; + + } // switch return std::string(); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits