예제 #1
0
        /// <summary>
        /// Allocate a new swapper id for the given <seealso cref="PageSwapper"/>.
        /// </summary>
        internal int Allocate(PageSwapper swapper)
        {
            lock (this)
            {
                SwapperMapping[] swapperMappings = this._swapperMappings;

                // First look for an available freed slot.
                lock ( _free )
                {
                    if (!_free.Empty)
                    {
                        int id = _free.intIterator().next();
                        _free.remove(id);
                        swapperMappings[id]   = new SwapperMapping(id, swapper);
                        this._swapperMappings = swapperMappings;                                  // Volatile store synchronizes-with loads in getters.
                        return(id);
                    }
                }

                // No free slot was found above, so we extend the array to make room for a new slot.
                int id = swapperMappings.Length;
                if (id + 1 > _maxSwapperId)
                {
                    throw new System.InvalidOperationException("All swapper ids are allocated: " + _maxSwapperId);
                }
                swapperMappings       = Arrays.copyOf(swapperMappings, id + 1);
                swapperMappings[id]   = new SwapperMapping(id, swapper);
                this._swapperMappings = swapperMappings;                   // Volatile store synchronizes-with loads in getters.
                return(id);
            }
        }
예제 #2
0
        /// <summary>
        /// Get the <seealso cref="SwapperMapping"/> for the given swapper id.
        /// </summary>
        internal SwapperMapping GetAllocation(int id)
        {
            CheckId(id);
            SwapperMapping swapperMapping = _swapperMappings[id];

            if (swapperMapping == null || swapperMapping == _tombstone)
            {
                return(null);
            }
            return(swapperMapping);
        }
예제 #3
0
        /// <summary>
        /// Collect all freed page swapper ids, and pass them to the given callback, after which the freed ids will be
        /// eligible for reuse.
        /// This is done with careful synchronisation such that allocating and freeing of ids is allowed to mostly proceed
        /// concurrently.
        /// </summary>
        internal void Vacuum(System.Action <IntSet> evictAllLoadedPagesCallback)
        {
            // We do this complicated locking to avoid blocking allocate() and free() as much as possible, while still only
            // allow a single thread to do vacuum at a time, and at the same time have consistent locking around the
            // set of free ids.
            lock ( _vacuumLock )
            {
                // Collect currently free ids.
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.eclipse.collections.api.set.primitive.MutableIntSet freeIds = new org.eclipse.collections.impl.set.mutable.primitive.IntHashSet();
                MutableIntSet    freeIds         = new IntHashSet();
                SwapperMapping[] swapperMappings = this._swapperMappings;
                for (int id = 0; id < swapperMappings.Length; id++)
                {
                    SwapperMapping swapperMapping = swapperMappings[id];
                    if (swapperMapping == _tombstone)
                    {
                        freeIds.add(id);
                    }
                }

                // Evict all of them without holding up the lock on the free id set. This allows allocate() and free() to
                // proceed concurrently with our eviction. This is safe because we know that the ids we are evicting cannot
                // possibly be reused until we remove them from the free id set, which we won't do until after we've evicted
                // all of their loaded pages.
                evictAllLoadedPagesCallback(freeIds);

                // Finally, all of the pages that remained in memory with an unmapped swapper id have been evicted. We can
                // now safely allow those ids to be reused. Note, however, that free() might have been called while we were
                // doing this, so we can't just free.clear() the set; no, we have to explicitly remove only those specific
                // ids whose pages we evicted.
                lock (this)
                {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.eclipse.collections.api.iterator.IntIterator itr = freeIds.intIterator();
                    IntIterator itr = freeIds.intIterator();
                    while (itr.hasNext())
                    {
                        int freeId = itr.next();
                        swapperMappings[freeId] = null;
                    }
                    this._swapperMappings = swapperMappings;                              // Volatile store synchronizes-with loads in getters.
                }
                lock ( _free )
                {
                    _free.addAll(freeIds);
                }
            }
        }
예제 #4
0
 /// <summary>
 /// Free the given swapper id, and return {@code true} if it is time for a
 /// <seealso cref="MuninnPageCache.vacuum(SwapperSet)"/>, otherwise it returns {@code false}.
 /// </summary>
 internal bool Free(int id)
 {
     lock (this)
     {
         CheckId(id);
         SwapperMapping[] swapperMappings = this._swapperMappings;
         SwapperMapping   current         = swapperMappings[id];
         if (current == null || current == _tombstone)
         {
             throw new System.InvalidOperationException("PageSwapper allocation id " + id + " is currently not allocated. Likely a double free bug.");
         }
         swapperMappings[id]   = _tombstone;
         this._swapperMappings = swapperMappings;                   // Volatile store synchronizes-with loads in getters.
         _freeCounter++;
         if (_freeCounter == 20)
         {
             _freeCounter = 0;
             return(true);
         }
         return(false);
     }
 }