public void TestCanReuseExclusive()
        {
            CloseableReference <int> cachedRef = _cache.Cache(KEY, NewReference(100), _entryStateObserver);

            cachedRef.Dispose();
            Assert.IsTrue(_isExclusive ?? false);
            cachedRef = _cache.Reuse(KEY);
            Assert.IsNotNull(cachedRef);
            Assert.IsFalse(_isExclusive ?? true);
            cachedRef.Dispose();
            Assert.IsFalse(_isExclusive ?? true);
        }
        public void TestCachingSameKeyTwice()
        {
            CloseableReference <int> originalRef1 = NewReference(110);
            CloseableReference <int> cachedRef1   = _cache.Cache(KEY, originalRef1);
            CloseableReference <int> cachedRef2a  = _cache.Get(KEY);
            CloseableReference <int> cachedRef2b  = cachedRef2a.Clone();
            CloseableReference <int> cachedRef3   = _cache.Get(KEY);

            CountingMemoryCache <string, int> .Entry entry1 = _cache._cachedEntries.Get(KEY);

            CloseableReference <int> cachedRef2 = _cache.Cache(KEY, NewReference(120));

            CountingMemoryCache <string, int> .Entry entry2 = _cache._cachedEntries.Get(KEY);
            Assert.AreNotSame(entry1, entry2);
            AssertOrphanWithCount(entry1, 3);
            AssertSharedWithCount(KEY, 120, 1);

            // Release the orphaned reference only when all clients are gone
            originalRef1.Dispose();
            cachedRef2b.Dispose();
            AssertOrphanWithCount(entry1, 3);
            cachedRef2a.Dispose();
            AssertOrphanWithCount(entry1, 2);
            cachedRef1.Dispose();
            AssertOrphanWithCount(entry1, 1);
            Assert.AreEqual(0, _releaseCallCount);
            cachedRef3.Dispose();
            AssertOrphanWithCount(entry1, 0);
            Assert.AreEqual(1, _releaseCallCount);
        }
        public void TestEviction_ByEvictionQueueSize()
        {
            CloseableReference <int> originalRef1 = NewReference(200);
            CloseableReference <int> valueRef1    = _cache.Cache(KEYS[1], originalRef1);

            originalRef1.Dispose();
            valueRef1.Dispose();
            CloseableReference <int> originalRef2 = NewReference(300);
            CloseableReference <int> valueRef2    = _cache.Cache(KEYS[2], originalRef2);

            originalRef2.Dispose();
            valueRef2.Dispose();
            CloseableReference <int> originalRef3 = NewReference(700);
            CloseableReference <int> valueRef3    = _cache.Cache(KEYS[3], originalRef3);

            originalRef3.Dispose();
            AssertTotalSize(3, 1200);
            AssertExclusivelyOwnedSize(2, 500);
            AssertExclusivelyOwned(KEYS[1], 200);
            AssertExclusivelyOwned(KEYS[2], 300);
            AssertSharedWithCount(KEYS[3], 700, 1);
            Assert.AreEqual(0, _releaseCallCount);

            // Closing the client reference for item3 will cause item1 to be evicted
            valueRef3.Dispose();
            AssertTotalSize(2, 1000);
            AssertExclusivelyOwnedSize(2, 1000);
            AssertNotCached(KEYS[1], 200);
            AssertExclusivelyOwned(KEYS[2], 300);
            AssertExclusivelyOwned(KEYS[3], 700);
            Assert.IsTrue(_releaseValues.Contains(200));
        }
        public void TestUpdatesCacheParams()
        {
            CloseableReference <int> originalRef = NewReference(700);
            CloseableReference <int> cachedRef   = _cache.Cache(KEYS[2], originalRef);

            originalRef.Dispose();
            cachedRef.Dispose();

            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);

            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);
            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);

            AssertTotalSize(1, 700);
            AssertExclusivelyOwnedSize(1, 700);

            _params = new MemoryCacheParams(
                500 /* cache max size */,
                CACHE_MAX_COUNT,
                CACHE_EVICTION_QUEUE_MAX_SIZE,
                CACHE_EVICTION_QUEUE_MAX_COUNT,
                CACHE_ENTRY_MAX_SIZE);
            _paramsSupplier = new MockSupplier <MemoryCacheParams>(_params);
            _cache.ForceUpdateCacheParams(_paramsSupplier);

            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);

            AssertTotalSize(0, 0);
            AssertExclusivelyOwnedSize(0, 0);
            Assert.IsTrue(_releaseValues.Contains(700));
        }
Exemple #5
0
        public void TestCloseReference()
        {
            CloseableReference <IDisposable> copy = _closeableReference.Clone();

            Assert.AreEqual(2, _closeableReference.GetUnderlyingReferenceTestOnly().GetRefCountTestOnly());
            copy.Dispose();
            Assert.AreEqual(1, _closeableReference.GetUnderlyingReferenceTestOnly().GetRefCountTestOnly());
        }
        public void TestToggleExclusive()
        {
            CloseableReference <int> cachedRef = _cache.Cache(KEY, NewReference(100), _entryStateObserver);

            cachedRef.Dispose();
            Assert.IsTrue(_isExclusive ?? false);
            _cache.Get(KEY);
            Assert.IsFalse(_isExclusive ?? true);
        }
        /// <summary>
        /// This has to be called before we get rid of this object in order to
        /// release underlying memory.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            CloseableReference <SoftwareBitmap> reference = DetachBitmapReference();

            if (reference != null)
            {
                reference.Dispose();
            }
        }
        public void TestClosingClientReference()
        {
            CloseableReference <int> cachedRef = _cache.Cache(KEY, NewReference(100));

            // cached item should get exclusively owned
            cachedRef.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(1, 100);
            AssertExclusivelyOwned(KEY, 100);
            Assert.AreEqual(0, _releaseCallCount);
        }
Exemple #9
0
        public void TestGet_Realloc()
        {
            CloseableReference <byte[]> arrayRef = _pool.Get(1);

            byte[] smallArray = arrayRef.Get();
            arrayRef.Dispose();

            arrayRef = _pool.Get(7);
            Assert.AreEqual(8, arrayRef.Get().Length);
            Assert.AreNotSame(smallArray, arrayRef.Get());
        }
        public void TestClosingOriginalReference()
        {
            CloseableReference <int> originalRef = NewReference(100);

            _cache.Cache(KEY, originalRef);
            // cache should make its own copy and closing the original reference after caching
            // should not affect the cached value
            originalRef.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 1);
            Assert.AreEqual(0, _releaseCallCount);
        }
        public void TestEviction_ByTotalCount()
        {
            // value 5 cannot fit the cache
            CloseableReference <int> originalRef1 = NewReference(110);
            CloseableReference <int> valueRef1    = _cache.Cache(KEYS[1], originalRef1);

            originalRef1.Dispose();
            CloseableReference <int> originalRef2 = NewReference(120);
            CloseableReference <int> valueRef2    = _cache.Cache(KEYS[2], originalRef2);

            originalRef2.Dispose();
            CloseableReference <int> originalRef3 = NewReference(130);
            CloseableReference <int> valueRef3    = _cache.Cache(KEYS[3], originalRef3);

            originalRef3.Dispose();
            CloseableReference <int> originalRef4 = NewReference(140);
            CloseableReference <int> valueRef4    = _cache.Cache(KEYS[4], originalRef4);

            originalRef4.Dispose();
            CloseableReference <int> originalRef5 = NewReference(150);
            CloseableReference <int> valueRef5    = _cache.Cache(KEYS[5], originalRef5);

            originalRef5.Dispose();
            AssertTotalSize(4, 500);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEYS[1], 110, 1);
            AssertSharedWithCount(KEYS[2], 120, 1);
            AssertSharedWithCount(KEYS[3], 130, 1);
            AssertSharedWithCount(KEYS[4], 140, 1);
            AssertNotCached(KEYS[5], 150);
            Assert.IsNull(valueRef5);

            // Closing the clients of cached items will make them viable for eviction
            valueRef1.Dispose();
            valueRef2.Dispose();
            valueRef3.Dispose();
            AssertTotalSize(4, 500);
            AssertExclusivelyOwnedSize(3, 360);

            // Value 4 can now fit after evicting value1
            valueRef4 = _cache.Cache(KEYS[5], NewReference(150));
            AssertTotalSize(4, 540);
            AssertExclusivelyOwnedSize(2, 250);
            AssertNotCached(KEYS[1], 110);
            AssertExclusivelyOwned(KEYS[2], 120);
            AssertExclusivelyOwned(KEYS[3], 130);
            AssertSharedWithCount(KEYS[4], 140, 1);
            AssertSharedWithCount(KEYS[5], 150, 1);
            Assert.IsTrue(_releaseValues.Contains(110));
        }
Exemple #12
0
        /// <summary>
        /// Reallocate the local buffer to hold the new length specified.
        /// Also copy over existing data to this new buffer.
        /// </summary>
        /// <param name="newLength">New length of buffer.</param>
        /// <exception cref="InvalidStreamException">
        /// If the stream is invalid.
        /// </exception>
        /// <exception cref="SizeTooLargeException">
        /// If the allocation from the pool fails.
        /// </exception>
        internal void Realloc(int newLength)
        {
            EnsureValid();
            /* Can the buffer handle @i more bytes, if not expand it */
            if (newLength <= _bufRef.Get().Size)
            {
                return;
            }

            NativeMemoryChunk newbuf = _pool.Get(newLength);

            _bufRef.Get().Copy(0, newbuf, 0, _count);
            _bufRef.Dispose();
            _bufRef = CloseableReference <NativeMemoryChunk> .of(newbuf, _pool);
        }
        public void TestInUseCount()
        {
            CloseableReference <int> cachedRef1 = _cache.Cache(KEY, NewReference(100));

            CloseableReference <int> cachedRef2a = _cache.Get(KEY);
            CloseableReference <int> cachedRef2b = cachedRef2a.Clone();

            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 2);

            CloseableReference <int> cachedRef3a = _cache.Get(KEY);
            CloseableReference <int> cachedRef3b = cachedRef3a.Clone();
            CloseableReference <int> cachedRef3c = cachedRef3b.Clone();

            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 3);

            cachedRef1.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 2);

            // All copies of cachedRef2a need to be closed for usage count to drop
            cachedRef2a.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 2);
            cachedRef2b.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 1);

            // All copies of cachedRef3a need to be closed for usage count to drop
            cachedRef3c.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 1);
            cachedRef3b.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEY, 100, 1);
            cachedRef3a.Dispose();
            AssertTotalSize(1, 100);
            AssertExclusivelyOwnedSize(1, 100);
            AssertExclusivelyOwned(KEY, 100);
        }
        public void TestEviction_ByTotalSize()
        {
            // Value 4 cannot fit the cache
            CloseableReference <int> originalRef1 = NewReference(400);
            CloseableReference <int> valueRef1    = _cache.Cache(KEYS[1], originalRef1);

            originalRef1.Dispose();
            CloseableReference <int> originalRef2 = NewReference(500);
            CloseableReference <int> valueRef2    = _cache.Cache(KEYS[2], originalRef2);

            originalRef2.Dispose();
            CloseableReference <int> originalRef3 = NewReference(100);
            CloseableReference <int> valueRef3    = _cache.Cache(KEYS[3], originalRef3);

            originalRef3.Dispose();
            CloseableReference <int> originalRef4 = NewReference(700);
            CloseableReference <int> valueRef4    = _cache.Cache(KEYS[4], originalRef4);

            originalRef4.Dispose();
            AssertTotalSize(3, 1000);
            AssertExclusivelyOwnedSize(0, 0);
            AssertSharedWithCount(KEYS[1], 400, 1);
            AssertSharedWithCount(KEYS[2], 500, 1);
            AssertSharedWithCount(KEYS[3], 100, 1);
            AssertNotCached(KEYS[4], 700);
            Assert.IsNull(valueRef4);

            // Closing the clients of cached items will make them viable for eviction
            valueRef1.Dispose();
            valueRef2.Dispose();
            valueRef3.Dispose();
            AssertTotalSize(3, 1000);
            AssertExclusivelyOwnedSize(3, 1000);

            // Value 4 can now fit after evicting value1 and value2
            valueRef4 = _cache.Cache(KEYS[4], NewReference(700));
            AssertTotalSize(2, 800);
            AssertExclusivelyOwnedSize(1, 100);
            AssertNotCached(KEYS[1], 400);
            AssertNotCached(KEYS[2], 500);
            AssertExclusivelyOwned(KEYS[3], 100);
            AssertSharedWithCount(KEYS[4], 700, 1);
            Assert.IsTrue(_releaseValues.Contains(400));
            Assert.IsTrue(_releaseValues.Contains(500));
        }
        public void TestRemoveAllMatchingPredicate()
        {
            CloseableReference <int> originalRef1 = NewReference(110);
            CloseableReference <int> valueRef1    = _cache.Cache(KEYS[1], originalRef1);

            originalRef1.Dispose();
            valueRef1.Dispose();
            CloseableReference <int> originalRef2 = NewReference(120);
            CloseableReference <int> valueRef2    = _cache.Cache(KEYS[2], originalRef2);

            originalRef2.Dispose();
            valueRef2.Dispose();
            CloseableReference <int> originalRef3 = NewReference(130);
            CloseableReference <int> valueRef3    = _cache.Cache(KEYS[3], originalRef3);

            originalRef3.Dispose();
            CountingMemoryCache <string, int> .Entry entry3 = _cache._cachedEntries.Get(KEYS[3]);
            CloseableReference <int> originalRef4           = NewReference(150);
            CloseableReference <int> valueRef4 = _cache.Cache(KEYS[4], originalRef4);

            originalRef4.Dispose();

            int numEvictedEntries = _cache.RemoveAll(
                new Predicate <string>(key => key.Equals(KEYS[2]) || key.Equals(KEYS[3])));

            Assert.AreEqual(2, numEvictedEntries);

            AssertTotalSize(2, 260);
            AssertExclusivelyOwnedSize(1, 110);
            AssertExclusivelyOwned(KEYS[1], 110);
            AssertNotCached(KEYS[2], 120);
            AssertOrphanWithCount(entry3, 1);
            AssertSharedWithCount(KEYS[4], 150, 1);

            Assert.IsTrue(_releaseValues.Contains(120));
            Assert.IsFalse(_releaseValues.Contains(130));

            valueRef3.Dispose();
            Assert.IsTrue(_releaseValues.Contains(130));
        }
        public void TestClear()
        {
            CloseableReference <int> originalRef1 = NewReference(110);
            CloseableReference <int> cachedRef1   = _cache.Cache(KEYS[1], originalRef1);

            originalRef1.Dispose();
            CountingMemoryCache <string, int> .Entry entry1 = _cache._cachedEntries.Get(KEYS[1]);
            CloseableReference <int> originalRef2           = NewReference(120);
            CloseableReference <int> cachedRef2             = _cache.Cache(KEYS[2], originalRef2);

            originalRef2.Dispose();
            cachedRef2.Dispose();

            _cache.Clear();
            AssertTotalSize(0, 0);
            AssertExclusivelyOwnedSize(0, 0);
            AssertOrphanWithCount(entry1, 1);
            AssertNotCached(KEYS[2], 120);
            Assert.IsTrue(_releaseValues.Contains(120));

            cachedRef1.Dispose();
            Assert.IsTrue(_releaseValues.Contains(110));
        }
        /// <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 <CloseableReference <CloseableImage> > consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener  = producerContext.Listener;
            string            requestId = producerContext.Id;

            listener.OnProducerStart(requestId, ProducerName);
            ImageRequest imageRequest             = producerContext.ImageRequest;
            object       callerContext            = producerContext.CallerContext;
            ICacheKey    cacheKey                 = _cacheKeyFactory.GetBitmapCacheKey(imageRequest, callerContext);
            IDictionary <string, string> extraMap = default(IDictionary <string, string>);

            CloseableReference <CloseableImage> cachedReference = _memoryCache.Get(cacheKey);

            if (cachedReference != null)
            {
                bool isFinal = cachedReference.Get().QualityInfo.IsOfFullQuality;
                if (isFinal)
                {
                    extraMap = new Dictionary <string, string>()
                    {
                        { VALUE_FOUND, "true" }
                    };

                    listener.OnProducerFinishWithSuccess(
                        requestId,
                        ProducerName,
                        listener.RequiresExtraMap(requestId) ?
                        new ReadOnlyDictionary <string, string>(extraMap) :
                        null);

                    consumer.OnProgressUpdate(1f);
                }

                consumer.OnNewResult(cachedReference, isFinal);
                cachedReference.Dispose();
                if (isFinal)
                {
                    return;
                }
            }

            if (producerContext.LowestPermittedRequestLevel >= RequestLevel.BITMAP_MEMORY_CACHE)
            {
                extraMap = new Dictionary <string, string>()
                {
                    { VALUE_FOUND, "false" }
                };

                listener.OnProducerFinishWithSuccess(
                    requestId,
                    ProducerName,
                    listener.RequiresExtraMap(requestId) ?
                    new ReadOnlyDictionary <string, string>(extraMap) :
                    null);

                consumer.OnNewResult(null, true);
                return;
            }

            extraMap = new Dictionary <string, string>()
            {
                { VALUE_FOUND, "false" }
            };

            IConsumer <CloseableReference <CloseableImage> > wrappedConsumer =
                WrapConsumer(consumer, cacheKey);

            listener.OnProducerFinishWithSuccess(
                requestId,
                ProducerName,
                listener.RequiresExtraMap(requestId) ?
                new ReadOnlyDictionary <string, string>(extraMap) :
                null);

            _inputProducer.ProduceResults(wrappedConsumer, producerContext);
        }
Exemple #18
0
        /// <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 <CloseableReference <CloseableImage> > consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener      = producerContext.Listener;
            string            requestId     = producerContext.Id;
            ImageRequest      imageRequest  = producerContext.ImageRequest;
            object            callerContext = producerContext.CallerContext;

            // If there's no postprocessor or the postprocessor doesn't
            // require caching, forward results.
            IPostprocessor postprocessor = imageRequest.Postprocessor;

            if (postprocessor == null || postprocessor.PostprocessorCacheKey == null)
            {
                _inputProducer.ProduceResults(consumer, producerContext);
                return;
            }

            listener.OnProducerStart(requestId, ProducerName);
            ICacheKey cacheKey = _cacheKeyFactory.GetPostprocessedBitmapCacheKey(
                imageRequest, callerContext);

            CloseableReference <CloseableImage> cachedReference = _memoryCache.Get(cacheKey);
            var extraMap = default(Dictionary <string, string>);

            if (cachedReference != null)
            {
                extraMap = new Dictionary <string, string>()
                {
                    { VALUE_FOUND, "true" }
                };

                listener.OnProducerFinishWithSuccess(
                    requestId,
                    ProducerName,
                    listener.RequiresExtraMap(requestId) ?
                    new ReadOnlyDictionary <string, string>(extraMap) :
                    null);

                consumer.OnProgressUpdate(1.0f);
                consumer.OnNewResult(cachedReference, true);
                cachedReference.Dispose();
            }
            else
            {
                bool isRepeatedProcessor = postprocessor.GetType() == typeof(IRepeatedPostprocessor);
                IConsumer <CloseableReference <CloseableImage> > cachedConsumer =
                    new CachedPostprocessorConsumer(
                        consumer,
                        cacheKey,
                        isRepeatedProcessor,
                        _memoryCache);

                extraMap = new Dictionary <string, string>()
                {
                    { VALUE_FOUND, "false" }
                };

                listener.OnProducerFinishWithSuccess(
                    requestId,
                    ProducerName,
                    listener.RequiresExtraMap(requestId) ?
                    new ReadOnlyDictionary <string, string>(extraMap) :
                    null);

                _inputProducer.ProduceResults(cachedConsumer, producerContext);
            }
        }
Exemple #19
0
 /// <summary>
 /// Test cleanup.
 /// </summary>
 public void Dispose()
 {
     _mockCloseable.Dispose();
     _closeableReference.Dispose();
 }
 /// <summary>
 /// Test cleanup.
 /// </summary>
 public void Dispose()
 {
     _bitmap.Dispose();
     _platformBitmapFactory.Dispose();
     _bitmapReference.Dispose();
 }