/// <summary> /// Frees the allocation space borrowed earlier for some sync consumer. /// </summary> /// <param name="syncPeerAllocation">Allocation to free</param> public void Free(SyncPeerAllocation syncPeerAllocation) { if (_logger.IsTrace) { _logger.Trace($"Returning {syncPeerAllocation}"); } _replaceableAllocations.TryRemove(syncPeerAllocation, out _); syncPeerAllocation.Cancel(); if (_replaceableAllocations.Count > 1024 * 16) { _logger.Warn($"Peer allocations leakage - {_replaceableAllocations.Count}"); } SignalPeersChanged(); }
public async Task <SyncPeerAllocation> Allocate(IPeerAllocationStrategy peerAllocationStrategy, AllocationContexts allocationContexts = AllocationContexts.All, int timeoutMilliseconds = 0) { int tryCount = 1; DateTime startTime = DateTime.UtcNow; SyncPeerAllocation allocation = new SyncPeerAllocation(peerAllocationStrategy, allocationContexts); while (true) { lock (_isAllocatedChecks) { allocation.AllocateBestPeer(InitializedPeers.Where(p => p.CanBeAllocated(allocationContexts)), _stats, _blockTree); if (allocation.HasPeer) { if (peerAllocationStrategy.CanBeReplaced) { _replaceableAllocations.TryAdd(allocation, null); } return(allocation); } } bool timeoutReached = timeoutMilliseconds == 0 || (DateTime.UtcNow - startTime).TotalMilliseconds > timeoutMilliseconds; if (timeoutReached) { return(SyncPeerAllocation.FailedAllocation); } int waitTime = 10 * tryCount++; if (!_signals.SafeWaitHandle.IsClosed) { await _signals.WaitOneAsync(waitTime, _refreshLoopCancellation.Token); if (!_signals.SafeWaitHandle.IsClosed) { _signals.Reset(); // without this we have no delay } } } }