/// <summary> /// Updates our entries in the dictionary. To be immediately visible as soon as /// the _items.CanCommit() passes, we add ourselves into the dict straight away, /// and in a side effect we remove unnecessary entries, or, on rollback, undo /// the early additions. /// </summary> void UpdateEntries() { Shield.Enlist(this, false, true); var l = new Locals(); var oldItems = _items.GetOldValue(); var newItems = _items.Value; l.PreAdd = newItems == null ? null : (oldItems != null ? newItems.Except(oldItems).ToList() : newItems.ToList()); l.CommitRemove = oldItems == null ? null : (newItems != null ? oldItems.Except(newItems).ToList() : oldItems.ToList()); try { } finally { _locals.Value = l; var newArray = new[] { this }; // early adding if (l.PreAdd != null) { foreach (var newKey in l.PreAdd) { lock (Context) Context.AddOrUpdate(newKey, k => newArray, (k, existing) => existing.Concat(newArray).ToArray()); } } } }
/// <summary> /// Enlists the field in the current transaction and, if this is the first /// access, checks the write lock. Will wait (using StampLocker) if the write /// stamp <= <see cref="Shield.ReadStamp"/>, until write lock is released. /// Since write stamps are increasing, this is likely to happen only at the /// beginning of transactions. /// </summary> private void CheckLockAndEnlist(bool write) { // if already enlisted, no need to check lock. if (!Shield.Enlist(this, _locals.HasValue, write)) { return; } var ws = _writerStamp; if (ws != null && ws.Locked && ws.Version <= Shield.ReadStamp) { ws.Wait(); } }
private void CheckLockAndEnlist(TKey key, bool write) { var locals = _localDict.HasValue ? _localDict.Value : null; if (locals != null && locals.Locked) { CheckLockedAccess(key, write); return; // because the check above is much stricter than anything } if (!Shield.Enlist(this, locals != null, write) && locals.Items.ContainsKey(key)) { return; } WriteStamp w; if (_writeStamps.TryGetValue(key, out w) && w.Locked && w.Version <= Shield.ReadStamp) { w.Wait(); } }