Example #1
0
        private void Hit(WindowCache.Ref r)
        {
            // We don't need to be 100% accurate here. Its sufficient that at least
            // one thread performs the increment. Any other concurrent access at
            // exactly the same time can simply use the same clock value.
            //
            // Consequently we attempt the set, but we don't try to recover should
            // it fail. This is why we don't use getAndIncrement() here.
            //
            long c = clock.Get();

            clock.CompareAndSet(c, c + 1);
            r.lastAccess = c;
        }
Example #2
0
        /// <summary>Lookup a cached object, creating and loading it if it doesn't exist.</summary>
        /// <remarks>Lookup a cached object, creating and loading it if it doesn't exist.</remarks>
        /// <param name="pack">the pack that "contains" the cached object.</param>
        /// <param name="position">offset within <code>pack</code> of the object.</param>
        /// <returns>the object reference.</returns>
        /// <exception cref="System.IO.IOException">
        /// the object reference was not in the cache and could not be
        /// obtained by
        /// <see cref="Load(PackFile, long)">Load(PackFile, long)</see>
        /// .
        /// </exception>
        private ByteWindow GetOrLoad(PackFile pack, long position)
        {
            int slot = Slot(pack, position);

            WindowCache.Entry e1 = table.Get(slot);
            ByteWindow        v  = Scan(e1, pack, position);

            if (v != null)
            {
                return(v);
            }
            lock (LockCache(pack, position))
            {
                WindowCache.Entry e2 = table.Get(slot);
                if (e2 != e1)
                {
                    v = Scan(e2, pack, position);
                    if (v != null)
                    {
                        return(v);
                    }
                }
                v = Load(pack, position);
                WindowCache.Ref @ref = CreateRef(pack, position, v);
                Hit(@ref);
                for (; ;)
                {
                    WindowCache.Entry n = new WindowCache.Entry(Clean(e2), @ref);
                    if (table.CompareAndSet(slot, e2, n))
                    {
                        break;
                    }
                    e2 = table.Get(slot);
                }
            }
            if (evictLock.TryLock())
            {
                try
                {
                    Gc();
                    Evict();
                }
                finally
                {
                    evictLock.Unlock();
                }
            }
            return(v);
        }
Example #3
0
 private ByteWindow Scan(WindowCache.Entry n, PackFile pack, long position)
 {
     for (; n != null; n = n.next)
     {
         WindowCache.Ref r = n.@ref;
         if (r.pack == pack && r.position == position)
         {
             ByteWindow v = r.Get();
             if (v != null)
             {
                 Hit(r);
                 return(v);
             }
             n.Kill();
             break;
         }
     }
     return(null);
 }
Example #4
0
 internal Entry(WindowCache.Entry n, WindowCache.Ref r)
 {
     next = n;
     @ref = r;
 }
Example #5
0
 private void Clear(WindowCache.Ref @ref)
 {
     openBytes.AddAndGet([email protected]);
     Close(@ref.pack);
 }
Example #6
0
 private WindowCache.Ref CreateRef(PackFile p, long o, ByteWindow v)
 {
     WindowCache.Ref @ref = new WindowCache.Ref(p, o, v, queue);
     openBytes.AddAndGet(@ref.size);
     return(@ref);
 }