/// <summary> /// Instantiates the <see cref="ImagePipelineCore"/>. /// </summary> /// <param name="producerSequenceFactory"> /// The factory that creates all producer sequences. /// </param> /// <param name="requestListeners"> /// The listeners for the image requests. /// </param> /// <param name="isPrefetchEnabledSupplier"> /// The supplier for enabling prefetch. /// </param> /// <param name="bitmapMemoryCache"> /// The memory cache for CloseableImage. /// </param> /// <param name="encodedMemoryCache"> /// The memory cache for IPooledByteBuffer. /// </param> /// <param name="mainBufferedDiskCache"> /// The default buffered disk cache. /// </param> /// <param name="smallImageBufferedDiskCache"> /// The buffered disk cache used for small images. /// </param> /// <param name="cacheKeyFactory"> /// The factory that creates cache keys for the pipeline. /// </param> /// <param name="threadHandoffProducerQueue"> /// Move further computation to different thread. /// </param> /// <param name="flexByteArrayPool"> /// The memory pool use for BitmapImage conversion. /// </param> public ImagePipelineCore( ProducerSequenceFactory producerSequenceFactory, HashSet <IRequestListener> requestListeners, ISupplier <bool> isPrefetchEnabledSupplier, IMemoryCache <ICacheKey, CloseableImage> bitmapMemoryCache, IMemoryCache <ICacheKey, IPooledByteBuffer> encodedMemoryCache, BufferedDiskCache mainBufferedDiskCache, BufferedDiskCache smallImageBufferedDiskCache, ICacheKeyFactory cacheKeyFactory, ThreadHandoffProducerQueue threadHandoffProducerQueue, FlexByteArrayPool flexByteArrayPool) { _idCounter = 0; _producerSequenceFactory = producerSequenceFactory; _requestListener = new ForwardingRequestListener(requestListeners); _isPrefetchEnabledSupplier = isPrefetchEnabledSupplier; _bitmapMemoryCache = bitmapMemoryCache; _encodedMemoryCache = encodedMemoryCache; _mainBufferedDiskCache = mainBufferedDiskCache; _smallImageBufferedDiskCache = smallImageBufferedDiskCache; _cacheKeyFactory = cacheKeyFactory; _threadHandoffProducerQueue = threadHandoffProducerQueue; _flexByteArrayPool = flexByteArrayPool; _handleResultExecutor = Executors.NewFixedThreadPool(MAX_DATA_SOURCE_SUBSCRIBERS); }
/// <summary> /// Instantiates the <see cref="DiskCacheProducer"/>. /// </summary> public DiskCacheProducer( BufferedDiskCache defaultBufferedDiskCache, BufferedDiskCache smallImageBufferedDiskCache, ICacheKeyFactory cacheKeyFactory, IProducer <EncodedImage> inputProducer, int forceSmallCacheThresholdBytes) { _defaultBufferedDiskCache = defaultBufferedDiskCache; _smallImageBufferedDiskCache = smallImageBufferedDiskCache; _cacheKeyFactory = cacheKeyFactory; _inputProducer = inputProducer; _forceSmallCacheThresholdBytes = forceSmallCacheThresholdBytes; _chooseCacheByImageSize = (forceSmallCacheThresholdBytes > 0); }
public void Initialize() { // Initializes the IFileCache _fileCacheFactory = new DiskStorageCacheFactory(new DynamicDefaultDiskStorageFactory()); _fileCache = _fileCacheFactory.Get(DiskCacheConfig.NewBuilder().Build()); // Initializes the IPooledByteBufferFactory and PooledByteStreams _poolFactory = new PoolFactory(PoolConfig.NewBuilder().Build()); _byteBufferFactory = _poolFactory.PooledByteBufferFactory; _pooledByteStreams = _poolFactory.PooledByteStreams; // Initializes the IPooledByteBuffer from an image var file = StorageFile.GetFileFromApplicationUriAsync( new Uri("ms-appx:///Assets/SplashScreen.scale-200.png")).GetAwaiter().GetResult(); using (var stream = file.OpenReadAsync().GetAwaiter().GetResult()) { _pooledByteBuffer = _byteBufferFactory.NewByteBuffer( ByteStreams.ToByteArray(stream.AsStream())); } _closeableReference = CloseableReference <IPooledByteBuffer> .of(_pooledByteBuffer); _encodedImage = new EncodedImage(_closeableReference); _stagingArea = StagingArea.Instance; _imageCacheStatsTracker = NoOpImageCacheStatsTracker.Instance; // Initializes the cache keys IList <ICacheKey> keys = new List <ICacheKey>(); keys.Add(new SimpleCacheKey("http://test.uri")); keys.Add(new SimpleCacheKey("http://tyrone.uri")); keys.Add(new SimpleCacheKey("http://ian.uri")); _cacheKey = new MultiCacheKey(keys); // Initializes the executors _isCancelled = new AtomicBoolean(false); _readPriorityExecutor = Executors.NewFixedThreadPool(1); _writePriorityExecutor = Executors.NewFixedThreadPool(1); // Initializes the disk cache _bufferedDiskCache = new BufferedDiskCache( _fileCache, _byteBufferFactory, _pooledByteStreams, _readPriorityExecutor, _writePriorityExecutor, _imageCacheStatsTracker); }
public async Task TestSyncDiskCacheCheck() { await _bufferedDiskCache.Put(_cacheKey, _encodedImage); _fileCache = _fileCacheFactory.Get(DiskCacheConfig.NewBuilder().Build()); _stagingArea.ClearAll(); _bufferedDiskCache = new BufferedDiskCache( _fileCache, _byteBufferFactory, _pooledByteStreams, _readPriorityExecutor, _writePriorityExecutor, _imageCacheStatsTracker); Assert.IsTrue(_bufferedDiskCache.DiskCheckSync(_cacheKey)); }
private BufferedDiskCache GetSmallImageBufferedDiskCache() { if (_smallImageBufferedDiskCache == null) { _smallImageBufferedDiskCache = new BufferedDiskCache( GetSmallImageFileCache(), _config.PoolFactory.PooledByteBufferFactory, _config.PoolFactory.PooledByteStreams, _config.ExecutorSupplier.ForLocalStorageRead, _config.ExecutorSupplier.ForLocalStorageWrite, _config.ImageCacheStatsTracker); } return(_smallImageBufferedDiskCache); }
/// <summary> /// Instantiates the <see cref="DiskCacheConsumer"/>. /// </summary> internal DiskCacheConsumer( BufferedDiskCache defaultBufferedDiskCache, BufferedDiskCache smallImageBufferedDiskCache, bool chooseCacheByImageSize, int forceSmallCacheThresholdBytes, IConsumer <EncodedImage> consumer, BufferedDiskCache cache, ICacheKey cacheKey) : base(consumer) { _defaultBufferedDiskCache = defaultBufferedDiskCache; _smallImageBufferedDiskCache = smallImageBufferedDiskCache; _chooseCacheByImageSize = chooseCacheByImageSize; _forceSmallCacheThresholdBytes = forceSmallCacheThresholdBytes; _cache = cache; _cacheKey = cacheKey; }
/// <summary> /// Instantiates the <see cref="ProducerFactory"/> /// </summary> /// <param name="byteArrayPool"> /// The IByteArrayPool used by DecodeProducer. /// </param> /// <param name="imageDecoder"> /// The image decoder. /// </param> /// <param name="progressiveJpegConfig"> /// The progressive Jpeg configuration. /// </param> /// <param name="downsampleEnabled"> /// Enabling downsample. /// </param> /// <param name="resizeAndRotateEnabledForNetwork"> /// Enabling resize and rotate. /// </param> /// <param name="executorSupplier"> /// The supplier for tasks. /// </param> /// <param name="pooledByteBufferFactory"> /// The factory that allocates IPooledByteBuffer memory. /// </param> /// <param name="bitmapMemoryCache"> /// The memory cache for CloseableImage. /// </param> /// <param name="encodedMemoryCache"> /// The memory cache for IPooledByteBuffer. /// </param> /// <param name="defaultBufferedDiskCache"> /// The default buffered disk cache. /// </param> /// <param name="smallImageBufferedDiskCache"> /// The buffered disk cache used for small images. /// </param> /// <param name="cacheKeyFactory"> /// The factory that creates cache keys for the pipeline. /// </param> /// <param name="platformBitmapFactory"> /// The bitmap factory used for post process. /// </param> /// <param name="flexByteArrayPool"> /// The memory pool used for post process. /// </param> /// <param name="forceSmallCacheThresholdBytes"> /// The threshold set for using the small buffered disk cache. /// </param> public ProducerFactory( IByteArrayPool byteArrayPool, ImageDecoder imageDecoder, IProgressiveJpegConfig progressiveJpegConfig, bool downsampleEnabled, bool resizeAndRotateEnabledForNetwork, IExecutorSupplier executorSupplier, IPooledByteBufferFactory pooledByteBufferFactory, IMemoryCache <ICacheKey, CloseableImage> bitmapMemoryCache, IMemoryCache <ICacheKey, IPooledByteBuffer> encodedMemoryCache, BufferedDiskCache defaultBufferedDiskCache, BufferedDiskCache smallImageBufferedDiskCache, ICacheKeyFactory cacheKeyFactory, PlatformBitmapFactory platformBitmapFactory, FlexByteArrayPool flexByteArrayPool, int forceSmallCacheThresholdBytes) { _forceSmallCacheThresholdBytes = forceSmallCacheThresholdBytes; _byteArrayPool = byteArrayPool; _imageDecoder = imageDecoder; _progressiveJpegConfig = progressiveJpegConfig; _downsampleEnabled = downsampleEnabled; _resizeAndRotateEnabledForNetwork = resizeAndRotateEnabledForNetwork; _executorSupplier = executorSupplier; _pooledByteBufferFactory = pooledByteBufferFactory; _bitmapMemoryCache = bitmapMemoryCache; _encodedMemoryCache = encodedMemoryCache; _defaultBufferedDiskCache = defaultBufferedDiskCache; _smallImageBufferedDiskCache = smallImageBufferedDiskCache; _cacheKeyFactory = cacheKeyFactory; _platformBitmapFactory = platformBitmapFactory; _flexByteArrayPool = flexByteArrayPool; }
/// <summary> /// Start producing results for given context. /// Provided consumer is notified whenever progress is made /// (new value is ready or error occurs). /// </summary> public void ProduceResults( IConsumer <EncodedImage> consumer, IProducerContext producerContext) { ImageRequest imageRequest = producerContext.ImageRequest; if (!imageRequest.IsDiskCacheEnabled) { MaybeStartInputProducer(consumer, consumer, producerContext); return; } producerContext.Listener.OnProducerStart(producerContext.Id, PRODUCER_NAME); ICacheKey cacheKey = _cacheKeyFactory.GetEncodedCacheKey( imageRequest, producerContext.CallerContext); bool isSmallRequest = (imageRequest.CacheChoice == CacheChoice.SMALL); BufferedDiskCache preferredCache = isSmallRequest ? _smallImageBufferedDiskCache : _defaultBufferedDiskCache; AtomicBoolean isCancelled = new AtomicBoolean(false); Task <EncodedImage> diskLookupTask; if (_chooseCacheByImageSize) { bool alreadyInSmall = _smallImageBufferedDiskCache.ContainsSync(cacheKey); bool alreadyInMain = _defaultBufferedDiskCache.ContainsSync(cacheKey); BufferedDiskCache firstCache; BufferedDiskCache secondCache; if (alreadyInSmall || !alreadyInMain) { firstCache = _smallImageBufferedDiskCache; secondCache = _defaultBufferedDiskCache; } else { firstCache = _defaultBufferedDiskCache; secondCache = _smallImageBufferedDiskCache; } diskLookupTask = firstCache.Get(cacheKey, isCancelled); diskLookupTask = diskLookupTask.ContinueWith( task => { if (IsTaskCancelled(task) || (!task.IsFaulted && task.Result != null)) { return(task); } return(secondCache.Get(cacheKey, isCancelled)); }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap(); } else { diskLookupTask = preferredCache.Get(cacheKey, isCancelled); } diskLookupTask.ContinueWith( task => { OnFinishDiskReads( task, consumer, preferredCache, cacheKey, producerContext); }, TaskContinuationOptions.ExecuteSynchronously); SubscribeTaskForRequestCancellation(isCancelled, producerContext); }
private void OnFinishDiskReads( Task <EncodedImage> task, IConsumer <EncodedImage> consumer, BufferedDiskCache preferredCache, ICacheKey preferredCacheKey, IProducerContext producerContext) { string requestId = producerContext.Id; IProducerListener listener = producerContext.Listener; if (IsTaskCancelled(task)) { listener.OnProducerFinishWithCancellation(requestId, PRODUCER_NAME, null); consumer.OnCancellation(); } else if (task.IsFaulted) { listener.OnProducerFinishWithFailure(requestId, PRODUCER_NAME, task.Exception, null); MaybeStartInputProducer( consumer, new DiskCacheConsumer( _defaultBufferedDiskCache, _smallImageBufferedDiskCache, _chooseCacheByImageSize, _forceSmallCacheThresholdBytes, consumer, preferredCache, preferredCacheKey), producerContext); } else { EncodedImage cachedReference = task.Result; if (cachedReference != null) { listener.OnProducerFinishWithSuccess( requestId, PRODUCER_NAME, GetExtraMap(listener, requestId, true)); consumer.OnProgressUpdate(1); consumer.OnNewResult(cachedReference, true); cachedReference.Dispose(); } else { listener.OnProducerFinishWithSuccess( requestId, PRODUCER_NAME, GetExtraMap(listener, requestId, false)); MaybeStartInputProducer( consumer, new DiskCacheConsumer( _defaultBufferedDiskCache, _smallImageBufferedDiskCache, _chooseCacheByImageSize, _forceSmallCacheThresholdBytes, consumer, preferredCache, preferredCacheKey), producerContext); } } }