mirror of
https://github.com/LibreOffice/online.git
synced 2025-08-15 21:13:02 +00:00
wsd: improved TileCache
* Excised TileCacheDesc to improve performance and simplify code. * clang-tidy suggestions and auto-rewrite fixes. * Const-correctness. * Inlined and improved a couple of trivial functions (that are called often). * Reduced some logs from INF to DBG as they are only meaningful to devs. Change-Id: I1c4eb8c63da49aa061afbf3eb68cae23d4d5e7f3 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/98661 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Tested-by: Jenkins Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
This commit is contained in:

committed by
Ashod Nakashian

parent
c0b4eec80b
commit
aba09e165b
@ -51,65 +51,29 @@ public:
|
||||
_y2 = rectangle._y2;
|
||||
}
|
||||
|
||||
void setLeft(int x1)
|
||||
{
|
||||
_x1 = x1;
|
||||
}
|
||||
void setLeft(int x1) { _x1 = x1; }
|
||||
|
||||
int getLeft() const
|
||||
{
|
||||
return _x1;
|
||||
}
|
||||
int getLeft() const { return _x1; }
|
||||
|
||||
void setRight(int x2)
|
||||
{
|
||||
_x2 = x2;
|
||||
}
|
||||
void setRight(int x2) { _x2 = x2; }
|
||||
|
||||
int getRight() const
|
||||
{
|
||||
return _x2;
|
||||
}
|
||||
int getRight() const { return _x2; }
|
||||
|
||||
void setTop(int y1)
|
||||
{
|
||||
_y1 = y1;
|
||||
}
|
||||
void setTop(int y1) { _y1 = y1; }
|
||||
|
||||
int getTop() const
|
||||
{
|
||||
return _y1;
|
||||
}
|
||||
int getTop() const { return _y1; }
|
||||
|
||||
void setBottom(int y2)
|
||||
{
|
||||
_y2 = y2;
|
||||
}
|
||||
void setBottom(int y2) { _y2 = y2; }
|
||||
|
||||
int getBottom() const
|
||||
{
|
||||
return _y2;
|
||||
}
|
||||
int getBottom() const { return _y2; }
|
||||
|
||||
int getWidth()
|
||||
{
|
||||
return _x2 - _x1;
|
||||
}
|
||||
int getWidth() const { return _x2 - _x1; }
|
||||
|
||||
int getHeight()
|
||||
{
|
||||
return _y2 - _y1;
|
||||
}
|
||||
int getHeight() const { return _y2 - _y1; }
|
||||
|
||||
bool isValid()
|
||||
{
|
||||
return _x1 <= _x2 && _y1 <= _y2;
|
||||
}
|
||||
bool isValid() const { return _x1 <= _x2 && _y1 <= _y2; }
|
||||
|
||||
bool hasSurface()
|
||||
{
|
||||
return _x1 < _x2 && _y1 < _y2;
|
||||
}
|
||||
bool hasSurface() const { return _x1 < _x2 && _y1 < _y2; }
|
||||
|
||||
bool intersects(const Rectangle& rOther)
|
||||
{
|
||||
|
@ -180,11 +180,12 @@ public:
|
||||
|
||||
void TileCacheTests::testDesc()
|
||||
{
|
||||
TileCacheDesc descA = TileDesc(0, 0, 256, 256, 0, 0, 3200, 3200, /* ignored in cache */ 0, 1234, 1, true);
|
||||
TileCacheDesc descB = TileDesc(0, 0, 256, 256, 0, 0, 3200, 3200, /* ignored in cache */ 1, 1235, 2, false);
|
||||
TileDesc descA = TileDesc(0, 0, 256, 256, 0, 0, 3200, 3200, /* ignored in cache */ 0, 1234, 1, true);
|
||||
TileDesc descB = TileDesc(0, 0, 256, 256, 0, 0, 3200, 3200, /* ignored in cache */ 1, 1235, 2, false);
|
||||
|
||||
LOK_ASSERT_MESSAGE("versions do match", descA.getVersion() != descB.getVersion());
|
||||
LOK_ASSERT_MESSAGE("Compare includes fields it should not", descA == descB);
|
||||
TileDescCacheCompareEq pred;
|
||||
LOK_ASSERT_MESSAGE("TileDesc versions do match", descA.getVersion() != descB.getVersion());
|
||||
LOK_ASSERT_MESSAGE("TileDesc should match, ignoring unimportant fields", pred(descA, descB));
|
||||
}
|
||||
|
||||
void TileCacheTests::testSimple()
|
||||
|
@ -1615,10 +1615,10 @@ void ClientSession::removeOutdatedTilesOnFly()
|
||||
size_t ClientSession::countIdenticalTilesOnFly(const TileDesc& tile) const
|
||||
{
|
||||
size_t count = 0;
|
||||
std::string tileID = tile.generateID();
|
||||
for(auto& tileItem : _tilesOnFly)
|
||||
const std::string tileID = tile.generateID();
|
||||
for (const auto& tileItem : _tilesOnFly)
|
||||
{
|
||||
if(tileItem.first == tileID)
|
||||
if (tileItem.first == tileID)
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
|
@ -297,7 +297,7 @@ private:
|
||||
std::string _clipboardKeys[2];
|
||||
|
||||
/// TileID's of the sent tiles. Push by sending and pop by tileprocessed message from the client.
|
||||
std::list<std::pair<std::string, std::chrono::steady_clock::time_point>> _tilesOnFly;
|
||||
std::vector<std::pair<std::string, std::chrono::steady_clock::time_point>> _tilesOnFly;
|
||||
|
||||
/// Requested tiles are stored in this list, before we can send them to the client
|
||||
std::deque<TileDesc> _requestedTiles;
|
||||
|
@ -1681,12 +1681,6 @@ size_t DocumentBroker::getMemorySize() const
|
||||
_sessions.size() * sizeof(ClientSession);
|
||||
}
|
||||
|
||||
void DocumentBroker::invalidateTiles(const std::string& tiles, int normalizedViewId)
|
||||
{
|
||||
// Remove from cache.
|
||||
_tileCache->invalidateTiles(tiles, normalizedViewId);
|
||||
}
|
||||
|
||||
void DocumentBroker::handleTileRequest(TileDesc& tile,
|
||||
const std::shared_ptr<ClientSession>& session)
|
||||
{
|
||||
@ -1902,7 +1896,7 @@ void DocumentBroker::sendRequestedTiles(const std::shared_ptr<ClientSession>& se
|
||||
size_t delayedTiles = 0;
|
||||
std::vector<TileDesc> tilesNeedsRendering;
|
||||
size_t beingRendered = _tileCache->countTilesBeingRenderedForSession(session);
|
||||
while(session->getTilesOnFlyCount() + beingRendered < tilesOnFlyUpperLimit &&
|
||||
while (session->getTilesOnFlyCount() + beingRendered < tilesOnFlyUpperLimit &&
|
||||
!requestedTiles.empty() &&
|
||||
// If we delayed all tiles we don't send any tile (we will when next tileprocessed message arrives)
|
||||
delayedTiles < requestedTiles.size())
|
||||
@ -1916,7 +1910,7 @@ void DocumentBroker::sendRequestedTiles(const std::shared_ptr<ClientSession>& se
|
||||
requestedTiles.push_back(requestedTiles.front());
|
||||
requestedTiles.pop_front();
|
||||
delayedTiles += 1;
|
||||
LOG_INF("Requested tile was delayed!");
|
||||
LOG_DBG("Requested tile " << tile.getWireId() << " was delayed (already sent a version)!");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,12 @@ public:
|
||||
_cursorHeight = h;
|
||||
}
|
||||
|
||||
void invalidateTiles(const std::string& tiles, int normalizedViewId);
|
||||
void invalidateTiles(const std::string& tiles, int normalizedViewId)
|
||||
{
|
||||
// Remove from cache.
|
||||
_tileCache->invalidateTiles(tiles, normalizedViewId);
|
||||
}
|
||||
|
||||
void handleTileRequest(TileDesc& tile,
|
||||
const std::shared_ptr<ClientSession>& session);
|
||||
void handleTileCombinedRequest(TileCombined& tileCombined,
|
||||
|
@ -13,13 +13,14 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ClientSession.hpp"
|
||||
@ -31,13 +32,12 @@
|
||||
|
||||
using namespace LOOLProtocol;
|
||||
|
||||
TileCache::TileCache(const std::string& docURL,
|
||||
const std::chrono::system_clock::time_point& modifiedTime,
|
||||
bool dontCache) :
|
||||
_docURL(docURL),
|
||||
_dontCache(dontCache),
|
||||
_cacheSize(0),
|
||||
_maxCacheSize(512*1024)
|
||||
TileCache::TileCache(std::string docURL, const std::chrono::system_clock::time_point& modifiedTime,
|
||||
bool dontCache)
|
||||
: _docURL(std::move(docURL))
|
||||
, _dontCache(dontCache)
|
||||
, _cacheSize(0)
|
||||
, _maxCacheSize(512 * 1024)
|
||||
{
|
||||
#ifndef BUILDING_TESTS
|
||||
LOG_INF("TileCache ctor for uri [" << LOOLWSD::anonymizeUrl(_docURL) <<
|
||||
@ -61,6 +61,7 @@ void TileCache::clear()
|
||||
_cacheSize = 0;
|
||||
for (auto i : _streamCache)
|
||||
i.clear();
|
||||
|
||||
LOG_INF("Completely cleared tile cache for: " << _docURL);
|
||||
}
|
||||
|
||||
@ -69,9 +70,9 @@ void TileCache::clear()
|
||||
/// rendering latency.
|
||||
struct TileCache::TileBeingRendered
|
||||
{
|
||||
TileBeingRendered(const TileDesc& tile)
|
||||
: _startTime(std::chrono::steady_clock::now()),
|
||||
_tile(tile)
|
||||
explicit TileBeingRendered(const TileDesc& tile)
|
||||
: _startTime(std::chrono::steady_clock::now())
|
||||
, _tile(tile)
|
||||
{
|
||||
}
|
||||
|
||||
@ -95,19 +96,16 @@ private:
|
||||
size_t TileCache::countTilesBeingRenderedForSession(const std::shared_ptr<ClientSession>& session)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (auto &it : _tilesBeingRendered)
|
||||
for (auto& it : _tilesBeingRendered)
|
||||
{
|
||||
for (auto& s : it.second->getSubscribers())
|
||||
{
|
||||
for (auto &s : it.second->getSubscribers()) {
|
||||
if (s.lock() == session)
|
||||
count++;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool TileCache::hasTileBeingRendered(const std::shared_ptr<TileCache::TileBeingRendered>& tileBeingRendered)
|
||||
{
|
||||
return _tilesBeingRendered.find(tileBeingRendered->getTile()) != _tilesBeingRendered.end();
|
||||
return count;
|
||||
}
|
||||
|
||||
std::shared_ptr<TileCache::TileBeingRendered> TileCache::findTileBeingRendered(const TileDesc& tileDesc)
|
||||
@ -122,7 +120,7 @@ void TileCache::forgetTileBeingRendered(const std::shared_ptr<TileCache::TileBei
|
||||
{
|
||||
assertCorrectThread();
|
||||
assert(tileBeingRendered);
|
||||
assert(hasTileBeingRendered(tileBeingRendered));
|
||||
assert(hasTileBeingRendered(tileBeingRendered->getTile()));
|
||||
|
||||
LOG_TRC("Removing all subscribers for " << tileBeingRendered->getTile().serialize());
|
||||
_tilesBeingRendered.erase(tileBeingRendered->getTile());
|
||||
@ -132,23 +130,17 @@ double TileCache::getTileBeingRenderedElapsedTimeMs(const TileDesc &tileDesc) co
|
||||
{
|
||||
auto it = _tilesBeingRendered.find(tileDesc);
|
||||
if (it == _tilesBeingRendered.end())
|
||||
{
|
||||
return -1.0; // Negative value means that we did not find tileBeingRendered object
|
||||
}
|
||||
|
||||
return it->second->getElapsedTimeMs();
|
||||
}
|
||||
|
||||
bool TileCache::hasTileBeingRendered(const TileDesc& tile)
|
||||
{
|
||||
return findTileBeingRendered(tile) != nullptr;
|
||||
}
|
||||
|
||||
int TileCache::getTileBeingRenderedVersion(const TileDesc& tile)
|
||||
{
|
||||
std::shared_ptr<TileBeingRendered> tileBeingRendered = findTileBeingRendered(tile);
|
||||
if (tileBeingRendered)
|
||||
return tileBeingRendered->getVersion();
|
||||
else
|
||||
return 0;
|
||||
return tileBeingRendered ? tileBeingRendered->getVersion() : 0;
|
||||
}
|
||||
|
||||
TileCache::Tile TileCache::lookupTile(const TileDesc& tile)
|
||||
@ -169,8 +161,6 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
|
||||
{
|
||||
assertCorrectThread();
|
||||
|
||||
std::shared_ptr<TileBeingRendered> tileBeingRendered = findTileBeingRendered(tile);
|
||||
|
||||
// Save to disk.
|
||||
|
||||
// Ignore if we can't save the tile, things will work anyway, but slower.
|
||||
@ -179,6 +169,7 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
|
||||
LOG_TRC("Saved cache tile: " << cacheFileName(tile) << " of size " << size << " bytes");
|
||||
|
||||
// Notify subscribers, if any.
|
||||
std::shared_ptr<TileBeingRendered> tileBeingRendered = findTileBeingRendered(tile);
|
||||
if (tileBeingRendered)
|
||||
{
|
||||
const size_t subscriberCount = tileBeingRendered->getSubscribers().size();
|
||||
@ -254,7 +245,7 @@ bool TileCache::getTextStream(StreamType type, const std::string& fileName, std:
|
||||
|
||||
std::vector<char> buffer = *textStream;
|
||||
|
||||
if (buffer.size() > 0 && buffer.back() == '\n')
|
||||
if (!buffer.empty() && buffer.back() == '\n')
|
||||
buffer.pop_back();
|
||||
|
||||
content = std::string(buffer.data(), buffer.size());
|
||||
@ -286,7 +277,7 @@ TileCache::Tile TileCache::lookupCachedStream(StreamType type, const std::string
|
||||
LOG_TRC("Found stream cache tile: " << name << " of size " << it->second->size() << " bytes");
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
|
||||
return TileCache::Tile();
|
||||
}
|
||||
|
||||
@ -308,38 +299,44 @@ void TileCache::invalidateTiles(int part, int x, int y, int width, int height, i
|
||||
it = _cache.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileCache::invalidateTiles(const std::string& tiles, int normalizedViewId)
|
||||
{
|
||||
std::pair<int, Util::Rectangle> result = TileCache::parseInvalidateMsg(tiles);
|
||||
Util::Rectangle& invalidateRect = result.second;
|
||||
invalidateTiles(result.first, invalidateRect.getLeft(), invalidateRect.getTop(), invalidateRect.getWidth(), invalidateRect.getHeight(), normalizedViewId);
|
||||
const std::pair<int, Util::Rectangle> result = TileCache::parseInvalidateMsg(tiles);
|
||||
const Util::Rectangle& invalidateRect = result.second;
|
||||
invalidateTiles(result.first, invalidateRect.getLeft(), invalidateRect.getTop(),
|
||||
invalidateRect.getWidth(), invalidateRect.getHeight(), normalizedViewId);
|
||||
}
|
||||
|
||||
std::pair<int, Util::Rectangle> TileCache::parseInvalidateMsg(const std::string& tiles)
|
||||
{
|
||||
StringVector tokens = Util::tokenize(tiles);
|
||||
|
||||
assert(tokens.size() > 0 && tokens.equals(0, "invalidatetiles:"));
|
||||
assert(!tokens.empty() && tokens.equals(0, "invalidatetiles:"));
|
||||
|
||||
if (tokens.size() == 2 && tokens.equals(1, "EMPTY"))
|
||||
{
|
||||
return std::pair<int, Util::Rectangle>(-1, Util::Rectangle(0, 0, INT_MAX, INT_MAX));
|
||||
}
|
||||
else if (tokens.size() == 3 && tokens.equals(1, "EMPTY,"))
|
||||
|
||||
if (tokens.size() == 3 && tokens.equals(1, "EMPTY,"))
|
||||
{
|
||||
int part = 0;
|
||||
if (stringToInteger(tokens[2], part))
|
||||
{
|
||||
return std::pair<int, Util::Rectangle>(part, Util::Rectangle(0, 0, INT_MAX, INT_MAX));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int part, x, y, width, height;
|
||||
int part;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
if (tokens.size() == 6 &&
|
||||
getTokenInteger(tokens[1], "part", part) &&
|
||||
getTokenInteger(tokens[2], "x", x) &&
|
||||
@ -347,7 +344,6 @@ std::pair<int, Util::Rectangle> TileCache::parseInvalidateMsg(const std::string&
|
||||
getTokenInteger(tokens[4], "width", width) &&
|
||||
getTokenInteger(tokens[5], "height", height))
|
||||
{
|
||||
|
||||
return std::pair<int, Util::Rectangle>(part, Util::Rectangle(x, y, width, height));
|
||||
}
|
||||
}
|
||||
@ -375,9 +371,13 @@ std::string TileCache::cacheFileName(const TileDesc& tile)
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
bool TileCache::parseCacheFileName(const std::string& fileName, int& part, int& width, int& height, int& tilePosX, int& tilePosY, int& tileWidth, int& tileHeight, int& nviewid)
|
||||
bool TileCache::parseCacheFileName(const std::string& fileName, int& part, int& width, int& height,
|
||||
int& tilePosX, int& tilePosY, int& tileWidth, int& tileHeight,
|
||||
int& nviewid)
|
||||
{
|
||||
return std::sscanf(fileName.c_str(), "%d_%d_%dx%d.%d,%d.%dx%d.png", &nviewid, &part, &width, &height, &tilePosX, &tilePosY, &tileWidth, &tileHeight) == 8;
|
||||
return std::sscanf(fileName.c_str(), "%d_%d_%dx%d.%d,%d.%dx%d.png", &nviewid, &part, &width,
|
||||
&height, &tilePosX, &tilePosY, &tileWidth, &tileHeight)
|
||||
== 8;
|
||||
}
|
||||
|
||||
bool TileCache::intersectsTile(const TileDesc &tileDesc, int part, int x, int y, int width, int height, int normalizedViewId)
|
||||
@ -514,26 +514,23 @@ void TileCache::assertCorrectThread()
|
||||
{
|
||||
const bool correctThread = _owner == std::thread::id() || std::this_thread::get_id() == _owner;
|
||||
if (!correctThread)
|
||||
LOG_ERR("TileCache method invoked from foreign thread. Expected: " <<
|
||||
Log::to_string(_owner) << " but called from " <<
|
||||
std::this_thread::get_id() << " (" << Util::getThreadId() << ").");
|
||||
{
|
||||
LOG_ERR("TileCache method invoked from foreign thread. Expected: "
|
||||
<< Log::to_string(_owner) << " but called from " << std::this_thread::get_id()
|
||||
<< " (" << Util::getThreadId() << ").");
|
||||
}
|
||||
assert (correctThread);
|
||||
}
|
||||
|
||||
TileCache::Tile TileCache::findTile(const TileDesc &desc)
|
||||
{
|
||||
auto it = _cache.find(desc);
|
||||
if (it != _cache.end())
|
||||
{
|
||||
if (it->first.getNormalizedViewId() == desc.getNormalizedViewId())
|
||||
const auto it = _cache.find(desc);
|
||||
if (it != _cache.end() && it->first.getNormalizedViewId() == desc.getNormalizedViewId())
|
||||
{
|
||||
LOG_TRC("Found cache tile: " << desc.serialize() << " of size " << it->second->size() << " bytes");
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
return TileCache::Tile();
|
||||
}
|
||||
else
|
||||
|
||||
return TileCache::Tile();
|
||||
}
|
||||
|
||||
@ -563,13 +560,12 @@ size_t TileCache::itemCacheSize(const Tile &tile)
|
||||
void TileCache::assertCacheSize()
|
||||
{
|
||||
#ifdef ENABLE_DEBUG
|
||||
{
|
||||
size_t recalcSize = 0;
|
||||
for (auto &it : _cache) {
|
||||
for (const auto& it : _cache)
|
||||
{
|
||||
recalcSize += itemCacheSize(it.second);
|
||||
}
|
||||
assert(recalcSize == _cacheSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -591,6 +587,7 @@ void TileCache::ensureCacheSize()
|
||||
std::vector<WidSize> wids;
|
||||
for (const auto& it : _cache)
|
||||
wids.emplace_back(it.first.getWireId(), itemCacheSize(it.second));
|
||||
|
||||
std::sort(wids.begin(), wids.end(),
|
||||
[](const WidSize &a, const WidSize &b) { return a._wid < b._wid; });
|
||||
|
||||
@ -598,17 +595,19 @@ void TileCache::ensureCacheSize()
|
||||
TileWireId maxToRemove = wids.front()._wid;
|
||||
|
||||
// do we have (the very rare) WID wrap-around
|
||||
if (wids.back()._wid - wids.front()._wid > 256*256*256)
|
||||
if (wids.back()._wid - wids.front()._wid > 256 * 256 * 256)
|
||||
{
|
||||
maxToRemove = wids.back()._wid;
|
||||
// calculate which wid to start at.
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate which wid to start at.
|
||||
size_t total = 0;
|
||||
for (auto &it : wids)
|
||||
for (const auto &it : wids)
|
||||
{
|
||||
total += it._size;
|
||||
maxToRemove = it._wid;
|
||||
if (total > _maxCacheSize/4)
|
||||
if (total > _maxCacheSize / 4)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -624,8 +623,10 @@ void TileCache::ensureCacheSize()
|
||||
it = _cache.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_TRC("Cache is now of size " << _cacheSize << " and " <<
|
||||
_cache.size() << " entries after cleaning");
|
||||
@ -656,9 +657,11 @@ void TileCache::TileBeingRendered::dumpState(std::ostream& os)
|
||||
{
|
||||
std::shared_ptr<ClientSession> session = it.lock();
|
||||
if (session)
|
||||
{
|
||||
os << " " << session->getId() << ' ' << session->getUserId() << ' '
|
||||
<< session->getName() << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileCache::dumpState(std::ostream& os)
|
||||
@ -674,11 +677,14 @@ void TileCache::dumpState(std::ostream& os)
|
||||
int type = 0;
|
||||
for (const auto& i : _streamCache)
|
||||
{
|
||||
size_t num = 0, size = 0;
|
||||
size_t num = 0;
|
||||
size_t size = 0;
|
||||
for (const auto& it : i)
|
||||
{
|
||||
num++; size += it.second->size();
|
||||
num++;
|
||||
size += it.second->size();
|
||||
}
|
||||
|
||||
os << " stream cache: " << type++ << " num: " << num << " size: " << size << " bytes\n";
|
||||
for (const auto& it : i)
|
||||
{
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <Rectangle.hpp>
|
||||
@ -21,39 +21,26 @@
|
||||
|
||||
class ClientSession;
|
||||
|
||||
class TileCacheDesc : public TileDesc
|
||||
// The cache cares about only some properties.
|
||||
struct TileDescCacheCompareEq final
|
||||
{
|
||||
public:
|
||||
TileCacheDesc(const TileDesc ©)
|
||||
: TileDesc(copy)
|
||||
inline bool operator()(const TileDesc& l, const TileDesc& r) const
|
||||
{
|
||||
}
|
||||
|
||||
// The cache cares about only some properties.
|
||||
bool operator==(const TileCacheDesc& other) const
|
||||
{
|
||||
return _part == other._part &&
|
||||
_width == other._width &&
|
||||
_height == other._height &&
|
||||
_tilePosX == other._tilePosX &&
|
||||
_tilePosY == other._tilePosY &&
|
||||
_tileWidth == other._tileWidth &&
|
||||
_tileHeight == other._tileHeight &&
|
||||
_normalizedViewId == other._normalizedViewId;
|
||||
return l.getPart() == r.getPart() &&
|
||||
l.getWidth() == r.getWidth() &&
|
||||
l.getHeight() == r.getHeight() &&
|
||||
l.getTilePosX() == r.getTilePosX() &&
|
||||
l.getTilePosY() == r.getTilePosY() &&
|
||||
l.getTileWidth() == r.getTileWidth() &&
|
||||
l.getTileHeight() == r.getTileHeight() &&
|
||||
l.getNormalizedViewId() == r.getNormalizedViewId();
|
||||
}
|
||||
};
|
||||
|
||||
// The cache cares about only some properties.
|
||||
struct TileCacheDescCompareEqual
|
||||
struct TileDescCacheHasher final
|
||||
{
|
||||
bool operator()(const TileCacheDesc &l, const TileCacheDesc &r) const { return l == r; }
|
||||
};
|
||||
|
||||
// The cache cares about only some properties.
|
||||
struct TileCacheDescHasher
|
||||
{
|
||||
size_t
|
||||
operator()(const TileCacheDesc &t) const
|
||||
inline size_t operator()(const TileDesc& t) const
|
||||
{
|
||||
size_t hash = t.getPart();
|
||||
|
||||
@ -74,16 +61,16 @@ class TileCache
|
||||
{
|
||||
struct TileBeingRendered;
|
||||
|
||||
bool hasTileBeingRendered(const std::shared_ptr<TileCache::TileBeingRendered>& tileBeingRendered);
|
||||
std::shared_ptr<TileBeingRendered> findTileBeingRendered(const TileDesc& tile);
|
||||
|
||||
public:
|
||||
typedef std::shared_ptr<std::vector<char>> Tile;
|
||||
using Tile = std::shared_ptr<std::vector<char>>;
|
||||
|
||||
/// When the docURL is a non-file:// url, the timestamp has to be provided by the caller.
|
||||
/// For file:// url's, it's ignored.
|
||||
/// When it is missing for non-file:// url, it is assumed the document must be read, and no cached value used.
|
||||
TileCache(const std::string& docURL, const std::chrono::system_clock::time_point& modifiedTime, bool dontCache = false);
|
||||
TileCache(std::string docURL, const std::chrono::system_clock::time_point& modifiedTime,
|
||||
bool dontCache = false);
|
||||
~TileCache();
|
||||
|
||||
/// Completely clear the cache contents.
|
||||
@ -107,7 +94,7 @@ public:
|
||||
/// Find the tile with this description
|
||||
Tile lookupTile(const TileDesc& tile);
|
||||
|
||||
void saveTileAndNotify(const TileDesc& tile, const char* data, const size_t size);
|
||||
void saveTileAndNotify(const TileDesc& tile, const char* data, size_t size);
|
||||
|
||||
enum StreamType {
|
||||
Font,
|
||||
@ -140,7 +127,11 @@ public:
|
||||
double getTileBeingRenderedElapsedTimeMs(const TileDesc &tileDesc) const;
|
||||
|
||||
size_t countTilesBeingRenderedForSession(const std::shared_ptr<ClientSession>& session);
|
||||
bool hasTileBeingRendered(const TileDesc& tileDesc);
|
||||
inline bool hasTileBeingRendered(const TileDesc& tileDesc) const
|
||||
{
|
||||
return _tilesBeingRendered.find(tileDesc) != _tilesBeingRendered.end();
|
||||
}
|
||||
|
||||
int getTileBeingRenderedVersion(const TileDesc& tileDesc);
|
||||
|
||||
/// Set the high watermark for tilecache size
|
||||
@ -176,8 +167,9 @@ private:
|
||||
/// Extract location from fileName, and check if it intersects with [x, y, width, height].
|
||||
static bool intersectsTile(const TileDesc &tileDesc, int part, int x, int y, int width, int height, int normalizedViewId);
|
||||
|
||||
void saveDataToCache(const TileDesc &desc, const char *data, const size_t size);
|
||||
void saveDataToStreamCache(StreamType type, const std::string &fileName, const char *data, const size_t size);
|
||||
void saveDataToCache(const TileDesc& desc, const char* data, size_t size);
|
||||
void saveDataToStreamCache(StreamType type, const std::string& fileName, const char* data,
|
||||
size_t size);
|
||||
|
||||
const std::string _docURL;
|
||||
|
||||
@ -192,16 +184,16 @@ private:
|
||||
size_t _maxCacheSize;
|
||||
|
||||
// FIXME: should we have a tile-desc to WID map instead and a simpler lookup ?
|
||||
std::unordered_map<TileCacheDesc, Tile,
|
||||
TileCacheDescHasher,
|
||||
TileCacheDescCompareEqual> _cache;
|
||||
std::unordered_map<TileDesc, Tile,
|
||||
TileDescCacheHasher,
|
||||
TileDescCacheCompareEq> _cache;
|
||||
// FIXME: TileBeingRendered contains TileDesc too ...
|
||||
std::unordered_map<TileCacheDesc, std::shared_ptr<TileBeingRendered>,
|
||||
TileCacheDescHasher,
|
||||
TileCacheDescCompareEqual> _tilesBeingRendered;
|
||||
std::unordered_map<TileDesc, std::shared_ptr<TileBeingRendered>,
|
||||
TileDescCacheHasher,
|
||||
TileDescCacheCompareEq> _tilesBeingRendered;
|
||||
|
||||
// old-style file-name to data grab-bag.
|
||||
std::map<std::string, Tile> _streamCache[(int)StreamType::Last];
|
||||
std::map<std::string, Tile> _streamCache[static_cast<int>(StreamType::Last)];
|
||||
};
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
@ -19,8 +19,8 @@
|
||||
#include <Protocol.hpp>
|
||||
|
||||
#define TILE_WIRE_ID
|
||||
typedef uint32_t TileWireId;
|
||||
typedef uint64_t TileBinaryHash;
|
||||
using TileWireId = uint32_t;
|
||||
using TileBinaryHash = uint64_t;
|
||||
|
||||
/// Tile Descriptor
|
||||
/// Represents a tile's coordinates and dimensions.
|
||||
@ -57,6 +57,7 @@ public:
|
||||
throw BadArgumentException("Invalid tile descriptor.");
|
||||
}
|
||||
}
|
||||
|
||||
int getNormalizedViewId() const { return _normalizedViewId; }
|
||||
void setNormalizedViewId(const int normalizedViewId) { _normalizedViewId = normalizedViewId; }
|
||||
int getPart() const { return _part; }
|
||||
@ -144,14 +145,12 @@ public:
|
||||
{
|
||||
if (!onSameRow(other))
|
||||
return false;
|
||||
int gridX = getTilePosX() / getTileWidth();
|
||||
int gridXOther = other.getTilePosX() / other.getTileWidth();
|
||||
int delta = gridX - gridXOther;
|
||||
|
||||
const int gridX = getTilePosX() / getTileWidth();
|
||||
const int gridXOther = other.getTilePosX() / other.getTileWidth();
|
||||
const int delta = gridX - gridXOther;
|
||||
// a 4k screen - is sixteen 256 pixel wide tiles wide.
|
||||
if (delta < -16 || delta > 16)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return (delta >= -16 && delta <= 16);
|
||||
}
|
||||
|
||||
/// Serialize this instance into a string.
|
||||
@ -546,7 +545,7 @@ public:
|
||||
}
|
||||
|
||||
/// To support legacy / under-used renderTile
|
||||
TileCombined(const TileDesc &desc)
|
||||
explicit TileCombined(const TileDesc &desc)
|
||||
{
|
||||
_part = desc.getPart();
|
||||
_width = desc.getWidth();
|
||||
|
Reference in New Issue
Block a user