mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-25 22:56:11 +03:00
Fix demo further: clear tile processing logics, perform locking on tile level, delete tile if drawn process encountered _destroyed state.
This commit is contained in:
parent
207bc88aab
commit
cd60aff5dc
21
src/tile.js
21
src/tile.js
@ -268,6 +268,18 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, aja
|
||||
* @private
|
||||
*/
|
||||
this.processing = false;
|
||||
/**
|
||||
* Remembers last processing time of the tile, 1 if the tile has just been loaded.
|
||||
* @private
|
||||
*/
|
||||
this.lastProcess = 0;
|
||||
/**
|
||||
* Transforming flag, exempt the tile from any processing since it is being transformed to a drawer-compatible
|
||||
* format. This process cannot be paused and the tile cannot be touched during the process. Used externally.
|
||||
* @member {Boolean|Number}
|
||||
* @private
|
||||
*/
|
||||
this.transforming = false;
|
||||
};
|
||||
|
||||
/** @lends OpenSeadragon.Tile.prototype */
|
||||
@ -603,15 +615,14 @@ $.Tile.prototype = {
|
||||
tileAllowNotLoaded: _allowTileNotLoaded
|
||||
});
|
||||
this.cacheKey = newCacheKey;
|
||||
return;
|
||||
}
|
||||
// If we requested restore, perform now
|
||||
if (requestedRestore) {
|
||||
} else if (requestedRestore) {
|
||||
// If we requested restore, perform now
|
||||
this.tiledImage._tileCache.restoreTilesThatShareOriginalCache(
|
||||
this, this.getCache(this.originalCacheKey), this.__restoreRequestedFree
|
||||
);
|
||||
}
|
||||
// Else no work to be done
|
||||
// If transforming was set, we finished: drawer transform always finishes with updateRenderTarget()
|
||||
this.transforming = false;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -163,15 +163,14 @@
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Access of the data by drawers, synchronous function.
|
||||
*
|
||||
* When drawers access data, they can choose to access this data as internal copy
|
||||
* Access of the data by drawers, synchronous function. Should always access a valid main cache, e.g.
|
||||
* cache swap should be atomic.
|
||||
*
|
||||
* @param {OpenSeadragon.DrawerBase} drawer
|
||||
* until 'setData' is called
|
||||
* @param {OpenSeadragon.Tile} tileDrawn
|
||||
* @returns {any|undefined} desired data if available, undefined if conversion must be done
|
||||
*/
|
||||
getDataForRendering(drawer) {
|
||||
getDataForRendering(drawer, tileDrawn) {
|
||||
const supportedTypes = drawer.getSupportedDataFormats(),
|
||||
keepInternalCopy = drawer.options.usePrivateCache;
|
||||
if (this.loaded && supportedTypes.includes(this.type)) {
|
||||
@ -180,6 +179,7 @@
|
||||
|
||||
if (this._destroyed) {
|
||||
$.console.error("Attempt to draw tile with destroyed main cache!");
|
||||
tileDrawn._unload(); // try to restore the state so that the tile is later on fetched again
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -2146,11 +2146,13 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
}).then(_ => {
|
||||
tile.loading = false;
|
||||
tile.loaded = true;
|
||||
tile.lastProcess = 1;
|
||||
resolver(tile);
|
||||
});
|
||||
} else {
|
||||
tile.loading = false;
|
||||
tile.loaded = true;
|
||||
tile.lastProcess = 1;
|
||||
resolver(tile);
|
||||
}
|
||||
}
|
||||
|
53
src/world.js
53
src/world.js
@ -249,11 +249,12 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
// const promise = this.requestTileInvalidateEvent(priorityTiles, tStamp, restoreTiles);
|
||||
// return promise.then(() => this.requestTileInvalidateEvent(this.viewer.tileCache.getLoadedTilesFor(null), tStamp, restoreTiles));
|
||||
|
||||
//
|
||||
//return this.requestTileInvalidateEvent(this.viewer.tileCache.getLoadedTilesFor(null), tStamp, restoreTiles);
|
||||
// Tile-first retrieval fires computation on tiles that share cache, which are filtered out by processing property
|
||||
return this.requestTileInvalidateEvent(this.viewer.tileCache.getLoadedTilesFor(null), tStamp, restoreTiles);
|
||||
|
||||
// Try go cache-first order, ensuring all tiles that do have cache entry get processed
|
||||
return this.requestTileInvalidateEvent(new Set(Object.values(this.viewer.tileCache._cachesLoaded).map(c => !c._destroyed && c._tiles[0])), tStamp, restoreTiles);
|
||||
// Cache-first update tile retrieval is nicer since there might be many tiles sharing
|
||||
// return this.requestTileInvalidateEvent(new Set(Object.values(this.viewer.tileCache._cachesLoaded)
|
||||
// .map(c => !c._destroyed && c._tiles[0])), tStamp, restoreTiles);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -268,23 +269,25 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
* @return {OpenSeadragon.Promise<?>}
|
||||
*/
|
||||
requestTileInvalidateEvent: function(tilesToProcess, tStamp, restoreTiles = true) {
|
||||
const tileList = [];
|
||||
const tileList = [],
|
||||
markedTiles = [];
|
||||
for (const tile of tilesToProcess) {
|
||||
//todo if tiles are processing then it does not update them to the latest stage
|
||||
// but if we do allow it, then a collision on processing occurs - swap in middle of rendering, we need
|
||||
// to check what is the latest processing stamp and if it is bigger than current process finish we need to abort
|
||||
if (!tile || !tile.loaded || tile.processing) { /* || tile.processing*/
|
||||
// We allow re-execution on tiles that are in process but have too low processing timestamp,
|
||||
// which must be solved by ensuring subsequent data calls in the suddenly outdated processing
|
||||
// pipeline take no effect.
|
||||
// TODO: cross writes on tile when processing cause memory errors - either ensure
|
||||
// tile makes NOOP for any execution that comes with older stamp, or prevent update routine
|
||||
// to happen simultanously
|
||||
if (!tile || !tile.loaded || (tile.processing && tile.processing <= tStamp) || tile.transforming) {
|
||||
continue;
|
||||
}
|
||||
// TODO: consider locking on the original cache, which should be read only
|
||||
// or lock the main cache, and compare with tile.processing tstamp
|
||||
const tileCache = tile.getCache();
|
||||
if (tileCache._updateStamp >= tStamp) {
|
||||
continue;
|
||||
}
|
||||
tileCache._updateStamp = tStamp;
|
||||
|
||||
for (let t of tileCache._tiles) {
|
||||
// Mark all as processing
|
||||
// Mark all related tiles as processing and cache the references to unmark later on
|
||||
t.processing = tStamp;
|
||||
markedTiles.push(t);
|
||||
}
|
||||
tileList.push(tile);
|
||||
}
|
||||
@ -307,23 +310,23 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
||||
tile: tile,
|
||||
tiledImage: tile.tiledImage,
|
||||
}).then(() => {
|
||||
// asynchronous finisher
|
||||
return tile.updateRenderTargetWithDataTransform(drawerId, supportedFormats, keepInternalCacheCopy);
|
||||
if (tile.processing === tStamp) {
|
||||
// asynchronous finisher
|
||||
tile.transforming = tStamp;
|
||||
return tile.updateRenderTargetWithDataTransform(drawerId, supportedFormats, keepInternalCacheCopy);
|
||||
}
|
||||
return null;
|
||||
}).catch(e => {
|
||||
$.console.error("Update routine error:", e);
|
||||
});
|
||||
});
|
||||
|
||||
return $.Promise.all(jobList).then(() => {
|
||||
for (let tile of tileList) {
|
||||
// pass update stamp on the new cache object to avoid needless updates
|
||||
const newCache = tile.getCache();
|
||||
if (newCache) {
|
||||
newCache._updateStamp = tStamp;
|
||||
tile.processing = false;
|
||||
}
|
||||
for (let tile of markedTiles) {
|
||||
tile.lastProcess = tile.processing;
|
||||
tile.processing = false;
|
||||
tile.transforming = false;
|
||||
}
|
||||
|
||||
this.draw();
|
||||
});
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user