public IDirectory RegisterDirectory(IDirectory directory) { cacheLock.EnterWriteLock(); try { var blockId = directory.BlockId; if (openedDirectories.TryGetValue(blockId, out var directoryWithRefCount)) { var existingDirectory = Volatile.Read(ref directoryWithRefCount.Directory); if (existingDirectory != null) { throw new InvalidOperationException($"Directory with blockId = {directory.BlockId} has already been registered"); } } directoryWithRefCount = new DirectoryWithRefCount { Directory = directory, RefCount = 1 }; openedDirectories[blockId] = directoryWithRefCount; return(directory); } finally { cacheLock.ExitWriteLock(); } }
public IDirectory ReadDirectory(int blockId) { cacheLock.EnterUpgradeableReadLock(); try { if (openedDirectories.TryGetValue(blockId, out var directoryWithRefCount)) { var directory = Volatile.Read(ref directoryWithRefCount.Directory); if (directory != null) { Interlocked.Increment(ref directoryWithRefCount.RefCount); return(directoryWithRefCount.Directory); } } cacheLock.EnterWriteLock(); try { if (openedDirectories.TryGetValue(blockId, out directoryWithRefCount)) { var directory = Volatile.Read(ref directoryWithRefCount.Directory); if (directory != null) { Interlocked.Increment(ref directoryWithRefCount.RefCount); return(directoryWithRefCount.Directory); } } directoryWithRefCount = new DirectoryWithRefCount { Directory = unsafeDirectoryReader.Read(blockId), RefCount = 1 }; openedDirectories.Add(blockId, directoryWithRefCount); return(directoryWithRefCount.Directory); } finally { cacheLock.ExitWriteLock(); } } finally { cacheLock.ExitUpgradeableReadLock(); } }