public Task Consumed(CommandMessage last) { if (last == null) { return(TplHelper.Empty); } using (_messagesLock.BeginUpgradeableReadLock()) { var messages = _clientMessages[last.ClientId]; var node = messages.Last; while (node != null && node.Value != last) { node = node.Previous; } using (_messagesLock.BeginWriteLock()) { while (node != null) { var previousNode = node.Previous; while (previousNode != null && previousNode.Value.ClientId != node.Value.ClientId) { previousNode = previousNode.Previous; } node.List.Remove(node); node = previousNode; } } } return(TplHelper.Empty); }
public void Insert(IKProtocolEndpoint <TNodeId> endpoint) { var b = false; using (sync.BeginWriteLock()) b = set.AddLast(endpoint); if (b) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, endpoint)); } }
public IDisposable Subscribe(IObserver <T> observer) { using (_observersLock.BeginWriteLock()) { _observers.Add(observer); if (_runningTask == null) { _runningTask = _whenHasObserver(_observersProxy); } } return(Disposable.Create(delegate { using (_observersLock.BeginWriteLock()) { _observers.Remove(observer); if (!_observers.Any() && _runningTask != null) { _runningTask.Dispose(); _runningTask = null; } } })); }
/// <summary> /// Updates the position of the node in the bucket. /// </summary> /// <typeparam name="TKNetwork"></typeparam> /// <param name="nodeId"></param> /// <param name="nodeData"></param> /// <param name="nodeEvents"></param> /// <param name="protocol"></param> /// <param name="cancellationToken"></param> internal async ValueTask TouchAsync(TKNodeId nodeId, TKNodeData nodeData, IKNodeEvents nodeEvents, IKNodeProtocol <TKNodeId, TKNodeData> protocol, CancellationToken cancellationToken) { var lk = rw.BeginUpgradableReadLock(); try { var i = GetNode(nodeId); if (i != null) { using (rw.BeginWriteLock()) { // item already exists, move to tail l.Remove(i); l.AddLast(i.Value); } } else if (l.Count < k) { using (rw.BeginWriteLock()) { // item does not exist, but bucket has room, insert at tail l.AddLast(new KBucketItem <TKNodeId, TKNodeData>(nodeId, nodeData, nodeEvents)); } } else { // item does not exist, but bucket does not have room, ping first entry var n = l.First; // start ping, check for async completion KNodePingResponse r; var t = protocol.PingAsync(n.Value.Id, n.Value.Data, cancellationToken); // completed synchronously (or immediately) if (t.IsCompleted) { r = t.Result; } else { // temporarily release lock and wait for completion lk.Dispose(); r = await t; lk = rw.BeginUpgradableReadLock(); } // was able to successfully ping the node if (r.Status == KNodeResponseStatus.OK) { // entry had response, move to tail, discard new entry if (l.Count > 1) { using (rw.BeginWriteLock()) { // remove from list if not already done (async operation could have overlapped) if (n.List != null) { l.Remove(n); } // node goes to end l.AddLast(n.Value); } } } else { using (rw.BeginWriteLock()) { // first entry had no response, remove, insert new at tail l.Remove(n); l.AddLast(new KBucketItem <TKNodeId, TKNodeData>(nodeId, nodeData, nodeEvents)); } } } } finally { lk.Dispose(); } }