public override async ReusableTask WriteAsync(ITorrentFileInfo file, long offset, byte[] buffer, int bufferOffset, int count) { var tcs = new ReusableTaskCompletionSource <object> (); Writes.Add(tcs); await tcs.Task; }
public static async ReusableTask ReceiveAsync(IConnection connection, ByteBuffer buffer, int offset, int count, IRateLimiter rateLimiter, SpeedMonitor peerMonitor, SpeedMonitor managerMonitor) { await MainLoop.SwitchToThreadpool(); while (count > 0) { int transferred; bool unlimited = rateLimiter?.Unlimited ?? true; int shouldRead = unlimited ? count : Math.Min(ChunkLength, count); if (rateLimiter != null && !unlimited && !rateLimiter.TryProcess(shouldRead)) { var tcs = new ReusableTaskCompletionSource <int> (); lock (receiveQueue) receiveQueue.Enqueue(new QueuedIO(connection, buffer, offset, shouldRead, rateLimiter, tcs)); transferred = await tcs.Task.ConfigureAwait(false); } else { transferred = await connection.ReceiveAsync(buffer, offset, shouldRead).ConfigureAwait(false); } if (transferred == 0) { throw new ConnectionClosedException("Socket receive returned 0, indicating the connection has been closed."); } peerMonitor?.AddDelta(transferred); managerMonitor?.AddDelta(transferred); offset += transferred; count -= transferred; } }
public static async ReusableTask SendAsync(IConnection2 connection, byte [] buffer, int offset, int count, IRateLimiter rateLimiter, SpeedMonitor peerMonitor, SpeedMonitor managerMonitor) { await IOLoop; while (count > 0) { int transferred; bool unlimited = rateLimiter?.Unlimited ?? true; var shouldRead = unlimited ? count : Math.Min(ChunkLength, count); if (rateLimiter != null && !unlimited && !rateLimiter.TryProcess(shouldRead)) { var tcs = new ReusableTaskCompletionSource <int> (); await IOLoop; sendQueue.Enqueue(new QueuedIO(connection, buffer, offset, shouldRead, rateLimiter, tcs)); transferred = await tcs.Task.ConfigureAwait(false); } else { transferred = await connection.SendAsync(buffer, offset, shouldRead).ConfigureAwait(false); } if (transferred == 0) { throw new Exception("Socket is dead"); } peerMonitor?.AddDelta(transferred); managerMonitor?.AddDelta(transferred); offset += transferred; count -= transferred; } }
public override async ReusableTask WriteAsync(ITorrentManagerFile file, long offset, ReadOnlyMemory <byte> buffer) { var tcs = new ReusableTaskCompletionSource <object> (); Writes.Add(tcs); await tcs.Task; }
public QueuedIO(IPeerConnection connection, SocketMemory buffer, IRateLimiter rateLimiter, ReusableTaskCompletionSource <int> tcs) { this.connection = connection; this.buffer = buffer; this.rateLimiter = rateLimiter; this.tcs = tcs; }
public async Task AllCombinations() { var tcs = new ReusableTaskCompletionSource <int>(); // write then read tcs.SetResult(1, true); var r1 = await tcs.GetResultAsync().ConfigureAwait(false); Assert.Equal(1, r1); // read then write var r2 = tcs.GetResultAsync(); Assert.False(r2.IsCompleted); tcs.SetResult(2, true); Assert.Equal(2, await r2.ConfigureAwait(false)); // read and await then write var r3 = Await(tcs.GetResultAsync()); Assert.False(r3.IsCompleted); tcs.SetResult(3, true); Assert.Equal(3, await r3.ConfigureAwait(false)); }
public async ReusableTask <Socket> ConnectAsync(Uri uri, CancellationToken token) { var socket = new Socket((uri.Scheme == "ipv4") ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); var endPoint = new IPEndPoint(IPAddress.Parse(uri.Host), uri.Port); using var registration = token.Register(SocketDisposer, socket); var tcs = new ReusableTaskCompletionSource <int> (); SocketAsyncEventArgs args = GetSocketAsyncEventArgs(); args.RemoteEndPoint = endPoint; args.UserToken = tcs; try { if (!socket.ConnectAsync(args)) { tcs.SetResult(0); } await tcs.Task; } catch { socket.Dispose(); throw; } finally { args.RemoteEndPoint = null; args.UserToken = null; lock (cache) cache.Enqueue(args); } return(socket); }
public async Task PingPong() { const int iterations = 1_000_000; var left = new ReusableTaskCompletionSource <int>(); var right = new ReusableTaskCompletionSource <int>(); async Task TestLeft() { for (int x = 0; x < iterations; ++x) { left.SetResult(x, true); (await right.GetResultAsync().ConfigureAwait(false)).Expect(x); } } async Task TestRight() { for (int x = 0; x < iterations; ++x) { (await left.GetResultAsync().ConfigureAwait(false)).Expect(x); right.SetResult(x, true); } } var t1 = TestLeft(); var t2 = TestRight(); await t1; await t2; }
async ReusableTask WaitForPendingWrites() { var tcs = new ReusableTaskCompletionSource <bool>(); WriteQueue.Enqueue(new BufferedIO(null, -1, null, -1, tcs)); await tcs.Task; }
public async Task ExceedMaxOpenFiles() { var streams = new List <ManualStream> (); var streamCreated = new ReusableTaskCompletionSource <bool> (); Func <ITorrentFileInfo, FileAccess, ITorrentFileStream> creator = (file, access) => { var s = new ManualStream(file, access); s.WriteTcs = new ReusableTaskCompletionSource <int> (); streams.Add(s); streamCreated.SetResult(true); return(s); }; using var writer = new DiskWriter(creator, 1); var writeTask = writer.WriteAsync(TorrentFile, 0, new byte[100], 0, 100); await streamCreated.Task.WithTimeout(); // There's a limit of 1 concurrent read/write. var secondStreamWaiter = streamCreated.Task.AsTask(); var secondStream = writer.WriteAsync(Others.First(), 0, new byte[100], 0, 100); Assert.ThrowsAsync <TimeoutException> (() => secondStreamWaiter.WithTimeout(100)); streams[0].WriteTcs.SetResult(1); await secondStreamWaiter.WithTimeout(); streams[1].WriteTcs.SetResult(1); await secondStream.WithTimeout(); Assert.IsTrue(streams[0].Disposed); Assert.IsFalse(streams[1].Disposed); }
public static async ReusableTask SendAsync(IPeerConnection connection, SocketMemory buffer, IRateLimiter rateLimiter, SpeedMonitor peerMonitor, SpeedMonitor managerMonitor) { await MainLoop.SwitchToThreadpool(); while (buffer.Length > 0) { int transferred; bool unlimited = rateLimiter?.Unlimited ?? true; int shouldRead = unlimited ? buffer.Length : Math.Min(ChunkLength, buffer.Length); if (rateLimiter != null && !unlimited && !rateLimiter.TryProcess(shouldRead)) { var tcs = new ReusableTaskCompletionSource <int> (); lock (sendQueue) sendQueue.Enqueue(new QueuedIO(connection, buffer.Slice(0, shouldRead), rateLimiter, tcs)); transferred = await tcs.Task.ConfigureAwait(false); } else { transferred = await connection.SendAsync(buffer.Slice(0, shouldRead)).ConfigureAwait(false); } if (transferred == 0) { throw new ConnectionClosedException("Socket send returned 0, indicating the connection has been closed."); } peerMonitor?.AddDelta(transferred); managerMonitor?.AddDelta(transferred); buffer = buffer.Slice(transferred); } }
SocketConnection(Socket socket, IPEndPoint endpoint, bool isIncoming) { ReceiveTcs = new ReusableTaskCompletionSource <int> (); SendTcs = new ReusableTaskCompletionSource <int> (); Socket = socket; EndPoint = endpoint; IsIncoming = isIncoming; }
public BufferedIO(ITorrentData manager, long offset, byte[] buffer, int count, ReusableTaskCompletionSource <bool> tcs) { this.manager = manager; this.offset = offset; this.buffer = buffer; this.count = count; this.tcs = tcs; }
public BufferedIO(ITorrentManagerInfo?manager, BlockInfo request, Memory <byte> buffer, bool preferSkipCache, ReusableTaskCompletionSource <bool> tcs) { this.manager = manager; this.request = request; this.buffer = buffer; this.preferSkipCache = preferSkipCache; this.tcs = tcs; }
public QueuedIO(IConnection2 connection, byte [] buffer, int offset, int count, IRateLimiter rateLimiter, ReusableTaskCompletionSource <int> tcs) { this.connection = connection; this.buffer = buffer; this.offset = offset; this.count = count; this.rateLimiter = rateLimiter; this.tcs = tcs; }
public async Task UseTwice() { var tcs = new ReusableTaskCompletionSource <int> (); tcs.SetResult(1); Assert.IsTrue(tcs.Task.IsCompleted, "#1"); Assert.AreEqual(1, await tcs.Task, "#2"); Assert.IsFalse(tcs.Task.IsCompleted, "#3"); Assert.AreEqual(0, ReusableTaskMethodBuilder <int> .CacheCount, "#4"); tcs.SetResult(2); Assert.AreEqual(2, await tcs.Task, "#6"); Assert.AreEqual(0, ReusableTaskMethodBuilder <int> .CacheCount, "#7"); }
internal async ReusableTask WriteAsync(ITorrentData manager, long offset, byte[] buffer, int count) { if (count < 1) { throw new ArgumentOutOfRangeException(nameof(count), $"Count must be greater than zero, but was {count}."); } Interlocked.Add(ref pendingWrites, count); await IOLoop; int pieceIndex = (int)(offset / manager.PieceLength); long pieceStart = (long)pieceIndex * manager.PieceLength; long pieceEnd = pieceStart + manager.PieceLength; if (!IncrementalHashes.TryGetValue(ValueTuple.Create(manager, pieceIndex), out IncrementalHashData incrementalHash) && offset == pieceStart) { incrementalHash = IncrementalHashes[ValueTuple.Create(manager, pieceIndex)] = IncrementalHashCache.Dequeue(); incrementalHash.NextOffsetToHash = (long)manager.PieceLength * pieceIndex; } if (incrementalHash != null) { // Incremental hashing does not perform proper bounds checking to ensure // that pieces are correctly incrementally hashed even if 'count' is greater // than the PieceLength. This should never happen under normal operation, but // unit tests do it for convenience sometimes. Keep things safe by cancelling // incremental hashing if that occurs. if ((incrementalHash.NextOffsetToHash + count) > pieceEnd) { IncrementalHashes.Remove(ValueTuple.Create(manager, pieceIndex)); } else if (incrementalHash.NextOffsetToHash == offset) { incrementalHash.Hasher.TransformBlock(buffer, 0, count, buffer, 0); incrementalHash.NextOffsetToHash += count; } } if (WriteLimiter.TryProcess(count)) { Interlocked.Add(ref pendingWrites, -count); Write(manager, offset, buffer, count); } else { var tcs = new ReusableTaskCompletionSource <bool> (); WriteQueue.Enqueue(new BufferedIO(manager, offset, buffer, count, tcs)); await tcs.Task; } }
public async ReusableTask ConnectAsync() { var tcs = new ReusableTaskCompletionSource <int> (); SocketAsyncEventArgs args = GetSocketAsyncEventArgs(null); args.RemoteEndPoint = EndPoint; args.UserToken = tcs; if (!Socket.ConnectAsync(args)) { tcs.SetResult(0); } await tcs.Task; }
public async Task DoNotForceAsyncWithSyncContext() { await TestSynchronizationContext.Instance; TestSynchronizationContext.Instance.ResetCounts(); var tcs = new ReusableTaskCompletionSource <int> (false); tcs.SetResult(1); // If we are not forcing async, we do allow synchronous completion. Assert.IsTrue(tcs.Task.IsCompleted, "#1"); await tcs.Task; Assert.AreEqual(0, TestSynchronizationContext.Instance.Posted, "#2"); }
public async Task ForceAsyncWithSyncContext() { await TestSynchronizationContext.Instance; TestSynchronizationContext.Instance.ResetCounts(); var tcs = new ReusableTaskCompletionSource <int> (true); tcs.SetResult(1); // If we're forcing async, we have to explicitly disallow synchronous completion too. Assert.IsFalse(tcs.Task.IsCompleted, "#1"); await tcs.Task; Assert.AreEqual(1, TestSynchronizationContext.Instance.Posted, "#2"); }
internal async ReusableTask <bool> ReadAsync(ITorrentData manager, long offset, byte [] buffer, int count) { Interlocked.Add(ref pendingReads, count); await IOLoop; if (ReadLimiter.TryProcess(count)) { Interlocked.Add(ref pendingReads, -count); return(Read(manager, offset, buffer, count)); } else { var tcs = new ReusableTaskCompletionSource <bool>(); ReadQueue.Enqueue(new BufferedIO(manager, offset, buffer, count, tcs)); return(await tcs.Task); } }
SocketPeerConnection(Uri?uri, ISocketConnector?connector, Socket?socket, bool isIncoming) { if (uri == null) { var endpoint = (IPEndPoint)socket !.RemoteEndPoint !; uri = new Uri($"{(socket.AddressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6") }://{endpoint.Address}{':'}{endpoint.Port}"); } ConnectCancellation = new CancellationTokenSource(); Connector = connector; EndPoint = new IPEndPoint(IPAddress.Parse(uri.Host), uri.Port); IsIncoming = isIncoming; Socket = socket; Uri = uri; ReceiveTcs = new ReusableTaskCompletionSource <int> (); SendTcs = new ReusableTaskCompletionSource <int> (); }
public async Task StressTest_Reuse() { var tasks = new List <Task> (); for (int count = 0; count < Environment.ProcessorCount * 2; count++) { tasks.Add(Task.Run(async() => { var tcs = new ReusableTaskCompletionSource <int>(); for (int i = 0; i < 50000; i++) { await Task.WhenAll( Task.Run(() => { tcs.SetResult(111); }), Task.Run(async() => { var result = await tcs.Task; Assert.AreEqual(111, result); }) ); } })); } await Task.WhenAll(tasks); }
public void NotInCache() { _ = new ReusableTaskCompletionSource <int> (); Assert.AreEqual(0, ReusableTaskMethodBuilder <int> .CacheCount, "#1"); }
async ReusableTask <bool> WaitForPendingWrites() { var tcs = new ReusableTaskCompletionSource <bool> (); WriteQueue.Enqueue(new BufferedIO(null, default, null, false, tcs));