/// <summary>
 /// Creates a new entry with the usage count of 0.
 /// </summary>
 internal static Entry of(
     K key,
     CloseableReference <V> valueRef,
     IEntryStateObserver <K> observer)
 {
     return(new Entry(key, valueRef, observer));
 }
 private Entry(K key, CloseableReference <V> valueRef, IEntryStateObserver <K> observer)
 {
     Key         = Preconditions.CheckNotNull(key);
     ValueRef    = Preconditions.CheckNotNull(CloseableReference <V> .CloneOrNull(valueRef));
     ClientCount = 0;
     Orphan      = false;
     Observer    = observer;
 }
        public void Initialize()
        {
            _releaseCallCount = 0;
            _releaseValues    = new List <int>();
            _releaser         = new ResourceReleaserImpl <int>(
                v =>
            {
                ++_releaseCallCount;
                _releaseValues.Add(v);
            });

            _onExclusivityChangedCallCount = 0;
            _isExclusive        = null;
            _entryStateObserver = new EntryStateObserverImpl <string>(
                (v, b) =>
            {
                ++_onExclusivityChangedCallCount;
                _isExclusive = b;
            });

            _cacheTrimStrategy = new CacheTrimStrategyImpl(v => _trimRatio);
            _valueDescriptor   = new ValueDescriptorImpl <int>(v => v);
            _params            = new MemoryCacheParams(
                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);
            _platformBitmapFactory = new MockPlatformBitmapFactory();
            _bitmap          = new SoftwareBitmap(BitmapPixelFormat.Rgba8, 50, 50);
            _bitmapReference = CloseableReference <SoftwareBitmap> .of(
                _bitmap, BITMAP_RESOURCE_RELEASER);

            _cache = new CountingMemoryCache <string, int>(
                _valueDescriptor,
                _cacheTrimStrategy,
                _paramsSupplier,
                _platformBitmapFactory,
                true);
        }
        /// <summary>
        /// Caches the given key-value pair.
        ///
        /// <para />Important: the client should use the returned reference
        /// instead of the original one. It is the caller's responsibility
        /// to close the returned reference once not needed anymore.
        /// </summary>
        /// <returns>
        /// The new reference to be used, null if the value cannot be cached.
        /// </returns>
        public CloseableReference <V> Cache(
            K key,
            CloseableReference <V> valueRef,
            IEntryStateObserver <K> observer)
        {
            Preconditions.CheckNotNull(key);
            Preconditions.CheckNotNull(valueRef);

            MaybeUpdateCacheParams();

            Entry oldExclusive;
            CloseableReference <V> oldRefToClose = null;
            CloseableReference <V> clientRef     = null;

            lock (_cacheGate)
            {
                // Remove the old item (if any) as it is stale now
                oldExclusive = _exclusiveEntries.Remove(key);
                Entry oldEntry = _cachedEntries.Remove(key);
                if (oldEntry != null)
                {
                    MakeOrphan(oldEntry);
                    oldRefToClose = ReferenceToClose(oldEntry);
                }

                if (CanCacheNewValue(valueRef.Get()))
                {
                    Entry newEntry = Entry.of(key, valueRef, observer);
                    _cachedEntries.Put(key, newEntry);
                    clientRef = NewClientReference(newEntry);
                }
            }

            CloseableReference <V> .CloseSafely(oldRefToClose);

            MaybeNotifyExclusiveEntryRemoval(oldExclusive);

            MaybeEvictEntries();
            return(clientRef);
        }