public bool TrySetNext(StreamBlockProxy next) { lock (this) { if (!NextTable.TryGetValue(this, out _)) { NextTable.Add(this, next); return(true); } return(false); } }
public StreamBlockProxy TryRentIndexedStreamBlockProxy(StreamLog streamLog, StreamBlockRecord record) { StreamBlockProxy p = null; while (p == null) { var blockKey = new BlockKey(streamLog.Slid, record.Version); // ReSharper disable once InconsistentlySynchronizedField if (_blocks.TryGetValue(blockKey, out var handle)) { p = handle.Target as StreamBlockProxy; } else { // CD.GetOrAdd factory is not atomic, lock manually. // Lock on SL, not a global object. This also helps // to avoid a capturing lambda and the risk of collecting // an object held only by a weak reference during that lambda return. lock (streamLog) { if (_blocks.TryGetValue(blockKey, out handle)) { p = handle.Target as StreamBlockProxy; } else { p = StreamBlockProxy.Create(blockKey, this); var sb = streamLog.GetBlockFromRecord(record); // Could set directly without SetStreamBlock p.Block = sb; handle = GCHandle.Alloc(p, GCHandleType.Weak); if (!_blocks.TryAdd(blockKey, handle)) { // this should never happen unless there are different streamLog instances for the same slid, // which in turn should never happen because SLs are stored in SLM dictionary. ThrowHelper.FailFast("Cannot add newly created StreamBlockProxy to cache from inside a lock."); } } } } // will be null if cannot retain, then will start over p = p?.TryRetain(); } return(p); }