public ImageStreamCompleter putIfAbsent(object key, Func <ImageStreamCompleter> loader) { D.assert(key != null); D.assert(loader != null); if (this._pendingImages.TryGetValue(key, out var result)) { return(result); } if (this._cache.TryGetValue(key, out var image)) { // put to the MRU position this._lruKeys.Remove(image.node); image.node = this._lruKeys.AddLast(key); return(image.completer); } result = loader(); if (this._maximumSize > 0 && this._maximumSizeBytes > 0) { D.assert(!this._pendingImages.ContainsKey(key)); this._pendingImages[key] = result; ImageListener listener = null; listener = (info, syncCall) => { result.removeListener(listener); D.assert(this._pendingImages.ContainsKey(key)); this._pendingImages.Remove(key); int imageSize = info?.image == null ? 0 : info.image.width & (info.image.height * 4); _CachedImage cachedImage = new _CachedImage { completer = result, sizeBytes = imageSize, }; // If the image is bigger than the maximum cache size, and the cache size // is not zero, then increase the cache size to the size of the image plus // some change. if (this._maximumSizeBytes > 0 && imageSize > this._maximumSizeBytes) { this._maximumSizeBytes = imageSize + 1000; } this._currentSizeBytes += imageSize; D.assert(!this._cache.ContainsKey(key)); this._cache[key] = cachedImage; cachedImage.node = this._lruKeys.AddLast(key); this._checkCacheSize(); }; result.addListener(listener); } return(result); }
void _touch(Object key, _CachedImage image) { // D.assert(foundation_.kReleaseMode); if (image.sizeBytes != null && image.sizeBytes <= maximumSizeBytes) { _currentSizeBytes += image.sizeBytes ?? 0; _cache[key] = image; // _checkCacheSize(timelineTask); } }
void _checkCacheSize() { while (this._currentSizeBytes > this._maximumSizeBytes || this._cache.Count > this._maximumSize) { var node = this._lruKeys.First; var key = node.Value; // get the LRU item D.assert(this._cache.ContainsKey(key)); _CachedImage image = this._cache[key]; D.assert(node == image.node); this._currentSizeBytes -= image.sizeBytes; this._cache.Remove(key); this._lruKeys.Remove(image.node); } D.assert(this._currentSizeBytes >= 0); D.assert(this._cache.Count <= this.maximumSize); D.assert(this._currentSizeBytes <= this.maximumSizeBytes); }
public ImageStreamCompleter putIfAbsent(object key, Func <ImageStreamCompleter> loader, ImageErrorListener onError = null) { D.assert(key != null); D.assert(loader != null); ImageStreamCompleter result = null; if (_pendingImages.TryGetValue(key, out var pendingImage)) { result = pendingImage.completer; return(result); } if (_cache.TryGetValue(key, out var image)) { if (image.node != null) { _lruKeys.Remove(image.node); } _trackLiveImage(key, new _LiveImage(image.completer, image.sizeBytes, () => _liveImages.Remove(key))); image.node = _lruKeys.AddLast(key); return(image.completer); } _liveImages.TryGetValue(key, out var liveImage); if (liveImage != null) { _touch(key, liveImage); return(liveImage.completer); } try { result = loader(); _trackLiveImage(key, new _LiveImage(result, null, () => _liveImages.Remove(key))); } catch (Exception ex) { if (onError != null) { onError(ex); } else { throw; } } bool listenedOnce = false; _PendingImage untrackedPendingImage = null; void listener(ImageInfo info, bool syncCall) { int imageSize = info?.image == null ? 0 : info.image.height * info.image.width * 4; _CachedImage cachedImage = new _CachedImage(result, imageSize); _trackLiveImage( key, new _LiveImage( result, imageSize, () => _liveImages.Remove(key) ), debugPutOk: syncCall ); _PendingImage _pendingImage = untrackedPendingImage ?? _pendingImages.getOrDefault(key); _pendingImages.Remove(key); if (_pendingImage != null) { _pendingImage.removeListener(); } if (untrackedPendingImage == null) { _touch(key, cachedImage); } listenedOnce = true; } ImageStreamListener streamListener = new ImageStreamListener(listener); if (maximumSize > 0 && maximumSizeBytes > 0) { _pendingImages[key] = new _PendingImage(result, streamListener); } else { untrackedPendingImage = new _PendingImage(result, streamListener); } result.addListener(streamListener); return(result); }
public ImageStreamCompleter putIfAbsent(object key, Func <ImageStreamCompleter> loader, ImageErrorListener onError = null) { D.assert(key != null); D.assert(loader != null); ImageStreamCompleter result = null; if (this._pendingImages.TryGetValue(key, out var pendingImage)) { result = pendingImage.completer; return(result); } if (this._cache.TryGetValue(key, out var image)) { // put to the MRU position this._lruKeys.Remove(image.node); image.node = this._lruKeys.AddLast(key); return(image.completer); } try { result = loader(); } catch (Exception ex) { if (onError != null) { onError(ex); } else { throw; } } void listener(ImageInfo info, bool syncCall) { int imageSize = info?.image == null ? 0 : info.image.height * info.image.width * 4; _CachedImage cachedImage = new _CachedImage(result, imageSize); if (this.maximumSizeBytes > 0 && imageSize > this.maximumSizeBytes) { this._maximumSizeBytes = imageSize + 1000; } this._currentSizeBytes += imageSize; if (this._pendingImages.TryGetValue(key, out var loadedPendingImage)) { loadedPendingImage.removeListener(); this._pendingImages.Remove(key); } D.assert(!this._cache.ContainsKey(key)); this._cache[key] = cachedImage; cachedImage.node = this._lruKeys.AddLast(key); this._checkCacheSize(); } if (this.maximumSize > 0 && this.maximumSizeBytes > 0) { this._pendingImages[key] = new _PendingImage(result, listener); result.addListener(listener); } return(result); }