public IFile RegisterFile(IFile file) { cacheLock.EnterWriteLock(); try { var blockId = file.BlockId; if (openedFiles.TryGetValue(blockId, out var fileWithRefCount)) { var existingFile = Volatile.Read(ref fileWithRefCount.File); if (existingFile != null) { throw new InvalidOperationException($"File with blockId = {file.BlockId} has already been registered"); } } fileWithRefCount = new FileWithRefCount { File = file, RefCount = 1 }; openedFiles[blockId] = fileWithRefCount; return(file); } finally { cacheLock.ExitWriteLock(); } }
public IFile ReadFile(int blockId, Func <IFile> readFile) { cacheLock.EnterUpgradeableReadLock(); try { if (openedFiles.TryGetValue(blockId, out var fileWithRefCount)) { var file = Volatile.Read(ref fileWithRefCount.File); if (file != null) { Interlocked.Increment(ref fileWithRefCount.RefCount); return(fileWithRefCount.File); } } cacheLock.EnterWriteLock(); try { if (openedFiles.TryGetValue(blockId, out fileWithRefCount)) { var file = Volatile.Read(ref fileWithRefCount.File); if (file != null) { Interlocked.Increment(ref fileWithRefCount.RefCount); return(fileWithRefCount.File); } } fileWithRefCount = new FileWithRefCount { File = readFile(), RefCount = 1 }; openedFiles.Add(blockId, fileWithRefCount); return(fileWithRefCount.File); } finally { cacheLock.ExitWriteLock(); } } finally { cacheLock.ExitUpgradeableReadLock(); } }