public CacheEntry CreateView(long offset, uint size, MemoryMappedFileAccess access) { if (_IsDisposed) throw new ObjectDisposedException("Cache"); if (access == MemoryMappedFileAccess.Write) access = MemoryMappedFileAccess.ReadWrite; int? freeSlot = null; int? oldestUsedSlot = null; long oldestUsedTimestamp = long.MaxValue; for (int i = 0; i < Capacity; i++) { var item = Cache[i]; if (item == null || item.IsDisposed) { freeSlot = i; continue; } if (item.CreatedWhen < oldestUsedTimestamp) oldestUsedSlot = i; if (offset < item.Offset) continue; if (offset + size > item.Offset + item.Size) continue; if (item.AddRef()) return item; else { freeSlot = i; break; } } if (!freeSlot.HasValue && !oldestUsedSlot.HasValue) throw new InvalidDataException(); long actualOffset; uint actualSize; var view = CreateViewUncached(offset, size, MemoryMappedFileAccess.ReadWrite, out actualOffset, out actualSize); var newEntry = new CacheEntry(view, actualOffset, actualSize); newEntry.AddRef(); long slotIndex = freeSlot.GetValueOrDefault(oldestUsedSlot.GetValueOrDefault(0)); var oldEntry = Interlocked.Exchange(ref Cache[slotIndex], newEntry); if (oldEntry != null) oldEntry.RemoveRef(); return newEntry; }
public CacheEntry CreateView(long offset, uint size, MemoryMappedFileAccess access) { if (_IsDisposed) { throw new ObjectDisposedException("Cache"); } if (access == MemoryMappedFileAccess.Write) { access = MemoryMappedFileAccess.ReadWrite; } int? freeSlot = null; int? oldestUsedSlot = null; long oldestUsedTimestamp = long.MaxValue; for (int i = 0; i < Capacity; i++) { var item = Cache[i]; if (item == null || item.IsDisposed) { freeSlot = i; continue; } if (item.CreatedWhen < oldestUsedTimestamp) { oldestUsedSlot = i; } if (offset < item.Offset) { continue; } if (offset + size > item.Offset + item.Size) { continue; } if (item.AddRef()) { return(item); } else { freeSlot = i; break; } } if (!freeSlot.HasValue && !oldestUsedSlot.HasValue) { throw new InvalidDataException(); } long actualOffset; uint actualSize; var view = CreateViewUncached(offset, size, MemoryMappedFileAccess.ReadWrite, out actualOffset, out actualSize); var newEntry = new CacheEntry(view, actualOffset, actualSize); newEntry.AddRef(); long slotIndex = freeSlot.GetValueOrDefault(oldestUsedSlot.GetValueOrDefault(0)); var oldEntry = Interlocked.Exchange(ref Cache[slotIndex], newEntry); if (oldEntry != null) { oldEntry.RemoveRef(); } return(newEntry); }