public override Task WriteAsync(ReadOnlyMemory <byte> source, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled(cancellationToken)); } try { // See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>). // Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency. if (source.DangerousTryGetArray(out ArraySegment <byte> sourceArray)) { Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count); } else { Write(source.Span); } return(Task.CompletedTask); } catch (OperationCanceledException oce) { return(Task.FromCancellation <VoidTaskResult>(oce)); } catch (Exception exception) { return(Task.FromException(exception)); } }
public virtual Task WriteAsync(ReadOnlyMemory <byte> source, CancellationToken cancellationToken = default(CancellationToken)) { if (source.DangerousTryGetArray(out ArraySegment <byte> array)) { return(WriteAsync(array.Array, array.Offset, array.Count, cancellationToken)); } else { byte[] buffer = ArrayPool <byte> .Shared.Rent(source.Length); source.Span.CopyTo(buffer); return(FinishWriteAsync(WriteAsync(buffer, 0, source.Length, cancellationToken), buffer)); async Task FinishWriteAsync(Task writeTask, byte[] localBuffer) { try { await writeTask.ConfigureAwait(false); } finally { ArrayPool <byte> .Shared.Return(localBuffer); } } } }
private static unsafe void AsMemory_Roundtrips_Core <T>(ReadOnlyMemory <T> readOnlyMemory) { Memory <T> memory = MemoryMarshal.AsMemory(readOnlyMemory); ReadOnlyMemory <T> readOnlyClone = memory; // Equals Assert.True(readOnlyMemory.Equals(readOnlyClone)); Assert.True(readOnlyMemory.Equals((object)readOnlyClone)); Assert.True(readOnlyMemory.Equals((object)memory)); // Span Assert.True(readOnlyMemory.Span == readOnlyClone.Span); Assert.True(readOnlyMemory.Span == memory.Span); // TryGetArray Assert.True(readOnlyMemory.DangerousTryGetArray(out ArraySegment <T> array1) == memory.TryGetArray(out ArraySegment <T> array2)); Assert.Same(array1.Array, array2.Array); Assert.Equal(array1.Offset, array2.Offset); Assert.Equal(array1.Count, array2.Count); // Retain using (MemoryHandle readOnlyMemoryHandle = readOnlyMemory.Retain()) using (MemoryHandle readOnlyCloneHandle = readOnlyMemory.Retain()) using (MemoryHandle memoryHandle = readOnlyMemory.Retain()) { Assert.Equal((IntPtr)readOnlyMemoryHandle.Pointer, (IntPtr)readOnlyCloneHandle.Pointer); Assert.Equal((IntPtr)readOnlyMemoryHandle.Pointer, (IntPtr)memoryHandle.Pointer); } }
public virtual Task WriteLineAsync(ReadOnlyMemory <char> source, CancellationToken cancellationToken = default(CancellationToken)) => source.DangerousTryGetArray(out ArraySegment <char> array) ? WriteLineAsync(array.Array, array.Offset, array.Count) : Task.Factory.StartNew(state => { var t = (Tuple <TextWriter, ReadOnlyMemory <char> >)state; t.Item1.WriteLine(t.Item2.Span); }, Tuple.Create(this, source), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
public static void AsReadOnlyMemory_TryGetArray_ReturnsFalse() { ReadOnlyMemory <char> m = "0123456789".AsReadOnlyMemory(); Assert.False(m.DangerousTryGetArray(out ArraySegment <char> array)); Assert.Null(array.Array); Assert.Equal(0, array.Offset); Assert.Equal(0, array.Count); }
public ReadOnlyMemoryContent(ReadOnlyMemory <byte> content) { _content = content; if (content.DangerousTryGetArray(out ArraySegment <byte> array)) { // If we have an array, allow HttpClient to take optimized paths by just // giving it the array content to use as its already buffered data. SetBuffer(array.Array, array.Offset, array.Count); } }
public static void MemoryDangerousTryGetArray() { int[] array = new int[10]; ReadOnlyMemory <int> memory = array; Assert.True(memory.DangerousTryGetArray(out ArraySegment <int> segment)); Assert.Equal(array.Length, segment.Count); for (int i = segment.Offset; i < segment.Count + segment.Offset; i++) { Assert.Equal(array[i], segment.Array[i]); } }
public static void OwnedMemoryTryGetArray() { int[] array = new int[10]; OwnedMemory <int> owner = new CustomMemoryForTest <int>(array); ReadOnlyMemory <int> memory = owner.AsMemory; Assert.True(memory.DangerousTryGetArray(out ArraySegment <int> segment)); Assert.Equal(array.Length, segment.Count); for (int i = segment.Offset; i < segment.Count + segment.Offset; i++) { Assert.Equal(array[i], segment.Array[i]); } }
public override async Task WriteAsync(ReadOnlyMemory <byte> source, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); // See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>). // Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency. if (source.DangerousTryGetArray(out ArraySegment <byte> sourceArray)) { Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count); } else { Write(source.Span); } }
private async Task WriteAsyncCore(ReadOnlyMemory <byte> source, CancellationToken cancellationToken) { Debug.Assert(this is NamedPipeClientStream || this is NamedPipeServerStream, $"Expected a named pipe, got a {GetType()}"); try { // TODO #22608: Remove this terribly inefficient special-case once Socket.SendAsync // accepts a Memory<T> in the near future. byte[] buffer; int offset, count; if (source.DangerousTryGetArray(out ArraySegment <byte> segment)) { buffer = segment.Array; offset = segment.Offset; count = segment.Count; } else { buffer = source.ToArray(); offset = 0; count = buffer.Length; } while (count > 0) { // cancellationToken is (mostly) ignored. We could institute a polling loop like we do for reads if // cancellationToken.CanBeCanceled, but that adds costs regardless of whether the operation will be canceled, and // most writes will complete immediately as they simply store data into the socket's buffer. The only time we end // up using it in a meaningful way is if a write completes partially, we'll check it on each individual write operation. cancellationToken.ThrowIfCancellationRequested(); int bytesWritten = await _handle.NamedPipeSocket.SendAsync(new ArraySegment <byte>(buffer, offset, count), SocketFlags.None).ConfigureAwait(false); Debug.Assert(bytesWritten <= count); count -= bytesWritten; offset += bytesWritten; } } catch (SocketException e) { throw GetIOExceptionForSocketException(e); } }
/// <summary>Implements Task-returning SendAsync on top of Begin/EndSend.</summary> private Task <int> SendAsyncApm(ReadOnlyMemory <byte> buffer, SocketFlags socketFlags) { if (buffer.DangerousTryGetArray(out ArraySegment <byte> bufferArray)) { var tcs = new TaskCompletionSource <int>(this); BeginSend(bufferArray.Array, bufferArray.Offset, bufferArray.Count, socketFlags, iar => { var innerTcs = (TaskCompletionSource <int>)iar.AsyncState; try { innerTcs.TrySetResult(((Socket)innerTcs.Task.AsyncState).EndSend(iar)); } catch (Exception e) { innerTcs.TrySetException(e); } }, tcs); return(tcs.Task); } else { // We weren't able to extract an underlying byte[] from the Memory<byte>. // Instead read into an ArrayPool array, then copy from that into the memory. byte[] poolArray = ArrayPool <byte> .Shared.Rent(buffer.Length); buffer.Span.CopyTo(poolArray); var tcs = new TaskCompletionSource <int>(this); BeginSend(poolArray, 0, buffer.Length, socketFlags, iar => { var state = (Tuple <TaskCompletionSource <int>, byte[]>)iar.AsyncState; try { state.Item1.TrySetResult(((Socket)state.Item1.Task.AsyncState).EndSend(iar)); } catch (Exception e) { state.Item1.TrySetException(e); } finally { ArrayPool <byte> .Shared.Return(state.Item2); } }, Tuple.Create(tcs, poolArray)); return(tcs.Task); } }
public static void TryGetArrayFromDefaultMemory() { ReadOnlyMemory <int> memory = default; Assert.False(memory.DangerousTryGetArray(out ArraySegment <int> segment)); Assert.True(segment.Equals(default));
private MemoryHandle _handle; // mutable struct; do not make this readonly internal MemoryFileStreamCompletionSource(FileStream stream, int numBufferedBytes, ReadOnlyMemory <byte> memory) : base(stream, numBufferedBytes, bytes: null) // this type handles the pinning, so null is passed for bytes { Debug.Assert(!memory.DangerousTryGetArray(out ArraySegment <byte> array), "The base should be used directly if we can get the array."); _handle = memory.Retain(pin: true); }
public virtual Task SendAsync(ReadOnlyMemory <byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) => buffer.DangerousTryGetArray(out ArraySegment <byte> arraySegment) ? SendAsync(arraySegment, messageType, endOfMessage, cancellationToken) : SendWithArrayPoolAsync(buffer, messageType, endOfMessage, cancellationToken);