mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-29 16:46:08 +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
|
* @private
|
||||||
*/
|
*/
|
||||||
this.processing = false;
|
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 */
|
/** @lends OpenSeadragon.Tile.prototype */
|
||||||
@ -603,15 +615,14 @@ $.Tile.prototype = {
|
|||||||
tileAllowNotLoaded: _allowTileNotLoaded
|
tileAllowNotLoaded: _allowTileNotLoaded
|
||||||
});
|
});
|
||||||
this.cacheKey = newCacheKey;
|
this.cacheKey = newCacheKey;
|
||||||
return;
|
} else if (requestedRestore) {
|
||||||
}
|
// If we requested restore, perform now
|
||||||
// If we requested restore, perform now
|
|
||||||
if (requestedRestore) {
|
|
||||||
this.tiledImage._tileCache.restoreTilesThatShareOriginalCache(
|
this.tiledImage._tileCache.restoreTilesThatShareOriginalCache(
|
||||||
this, this.getCache(this.originalCacheKey), this.__restoreRequestedFree
|
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
|
* @private
|
||||||
* Access of the data by drawers, synchronous function.
|
* Access of the data by drawers, synchronous function. Should always access a valid main cache, e.g.
|
||||||
*
|
* cache swap should be atomic.
|
||||||
* When drawers access data, they can choose to access this data as internal copy
|
|
||||||
*
|
*
|
||||||
* @param {OpenSeadragon.DrawerBase} drawer
|
* @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
|
* @returns {any|undefined} desired data if available, undefined if conversion must be done
|
||||||
*/
|
*/
|
||||||
getDataForRendering(drawer) {
|
getDataForRendering(drawer, tileDrawn) {
|
||||||
const supportedTypes = drawer.getSupportedDataFormats(),
|
const supportedTypes = drawer.getSupportedDataFormats(),
|
||||||
keepInternalCopy = drawer.options.usePrivateCache;
|
keepInternalCopy = drawer.options.usePrivateCache;
|
||||||
if (this.loaded && supportedTypes.includes(this.type)) {
|
if (this.loaded && supportedTypes.includes(this.type)) {
|
||||||
@ -180,6 +179,7 @@
|
|||||||
|
|
||||||
if (this._destroyed) {
|
if (this._destroyed) {
|
||||||
$.console.error("Attempt to draw tile with destroyed main cache!");
|
$.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;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2146,11 +2146,13 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|||||||
}).then(_ => {
|
}).then(_ => {
|
||||||
tile.loading = false;
|
tile.loading = false;
|
||||||
tile.loaded = true;
|
tile.loaded = true;
|
||||||
|
tile.lastProcess = 1;
|
||||||
resolver(tile);
|
resolver(tile);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
tile.loading = false;
|
tile.loading = false;
|
||||||
tile.loaded = true;
|
tile.loaded = true;
|
||||||
|
tile.lastProcess = 1;
|
||||||
resolver(tile);
|
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);
|
// const promise = this.requestTileInvalidateEvent(priorityTiles, tStamp, restoreTiles);
|
||||||
// return promise.then(() => this.requestTileInvalidateEvent(this.viewer.tileCache.getLoadedTilesFor(null), tStamp, restoreTiles));
|
// return promise.then(() => 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);
|
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
|
// 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);
|
// 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<?>}
|
* @return {OpenSeadragon.Promise<?>}
|
||||||
*/
|
*/
|
||||||
requestTileInvalidateEvent: function(tilesToProcess, tStamp, restoreTiles = true) {
|
requestTileInvalidateEvent: function(tilesToProcess, tStamp, restoreTiles = true) {
|
||||||
const tileList = [];
|
const tileList = [],
|
||||||
|
markedTiles = [];
|
||||||
for (const tile of tilesToProcess) {
|
for (const tile of tilesToProcess) {
|
||||||
//todo if tiles are processing then it does not update them to the latest stage
|
// We allow re-execution on tiles that are in process but have too low processing timestamp,
|
||||||
// but if we do allow it, then a collision on processing occurs - swap in middle of rendering, we need
|
// which must be solved by ensuring subsequent data calls in the suddenly outdated processing
|
||||||
// to check what is the latest processing stamp and if it is bigger than current process finish we need to abort
|
// pipeline take no effect.
|
||||||
if (!tile || !tile.loaded || tile.processing) { /* || tile.processing*/
|
// 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;
|
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();
|
const tileCache = tile.getCache();
|
||||||
if (tileCache._updateStamp >= tStamp) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tileCache._updateStamp = tStamp;
|
|
||||||
|
|
||||||
for (let t of tileCache._tiles) {
|
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;
|
t.processing = tStamp;
|
||||||
|
markedTiles.push(t);
|
||||||
}
|
}
|
||||||
tileList.push(tile);
|
tileList.push(tile);
|
||||||
}
|
}
|
||||||
@ -307,23 +310,23 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|||||||
tile: tile,
|
tile: tile,
|
||||||
tiledImage: tile.tiledImage,
|
tiledImage: tile.tiledImage,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// asynchronous finisher
|
if (tile.processing === tStamp) {
|
||||||
return tile.updateRenderTargetWithDataTransform(drawerId, supportedFormats, keepInternalCacheCopy);
|
// asynchronous finisher
|
||||||
|
tile.transforming = tStamp;
|
||||||
|
return tile.updateRenderTargetWithDataTransform(drawerId, supportedFormats, keepInternalCacheCopy);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
$.console.error("Update routine error:", e);
|
$.console.error("Update routine error:", e);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return $.Promise.all(jobList).then(() => {
|
return $.Promise.all(jobList).then(() => {
|
||||||
for (let tile of tileList) {
|
for (let tile of markedTiles) {
|
||||||
// pass update stamp on the new cache object to avoid needless updates
|
tile.lastProcess = tile.processing;
|
||||||
const newCache = tile.getCache();
|
tile.processing = false;
|
||||||
if (newCache) {
|
tile.transforming = false;
|
||||||
newCache._updateStamp = tStamp;
|
|
||||||
tile.processing = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.draw();
|
this.draw();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user