Skip to content

Commit

Permalink
Adding method implementations to fast span/readonlyspan (dotnet/corec…
Browse files Browse the repository at this point in the history
…lr#8607)




Commit migrated from dotnet/coreclr@f1391bb
  • Loading branch information
ahsonkhan authored and jkotas committed Dec 14, 2016
1 parent 473be98 commit 8170ac7
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 19 deletions.
10 changes: 8 additions & 2 deletions src/coreclr/src/mscorlib/model.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12424,6 +12424,7 @@
<Member Name="DangerousGetPinnableReference" />
<Member Name="op_Implicit(T[])" ReturnType="System.Span&lt;T&gt;" />
<Member Name="op_Implicit(System.ArraySegment&lt;T&gt;)" ReturnType="System.Span&lt;T&gt;" />
<Member Name="op_Implicit(System.Span&lt;T&gt;)" ReturnType="System.ReadOnlySpan&lt;T&gt;" />
<Member Name="op_Equality(System.Span&lt;T&gt;,System.Span&lt;T&gt;)" />
<Member Name="op_Inequality(System.Span&lt;T&gt;,System.Span&lt;T&gt;)" />
<Member Name="get_Length" />
Expand All @@ -12434,8 +12435,8 @@
<Member Name="ToArray" />
<Member Name="Slice(System.Int32)" />
<Member Name="Slice(System.Int32,System.Int32)" />
<Member Name="Equals(System.Span&lt;T&gt;)" />
<Member Name="Equals(System.Object)" />
<Member Name="DangerousCreate(System.Object,T@,System.Int32)" />
<Member Name="GetHashCode" />
<Member Name="CopyTo(System.Span&lt;T&gt;)" />
<Member Name="TryCopyTo(System.Span&lt;T&gt;)" />
Expand All @@ -12449,15 +12450,20 @@
<Member Name="op_Implicit(System.Span&lt;T&gt;)" ReturnType="System.ReadOnlySpan&lt;T&gt;" />
<Member Name="op_Implicit(T[])" ReturnType="System.ReadOnlySpan&lt;T&gt;" />
<Member Name="op_Implicit(System.ArraySegment&lt;T&gt;)" ReturnType="System.ReadOnlySpan&lt;T&gt;" />
<Member Name="op_Equality(System.ReadOnlySpan&lt;T&gt;,System.ReadOnlySpan&lt;T&gt;)" />
<Member Name="op_Inequality(System.ReadOnlySpan&lt;T&gt;,System.ReadOnlySpan&lt;T&gt;)" />
<Member Name="get_Length" />
<Member Name="get_Empty" />
<Member Name="get_IsEmpty" />
<Member Name="get_Item(System.Int32)" />
<Member Name="ToArray" />
<Member Name="Slice(System.Int32)" />
<Member Name="Slice(System.Int32,System.Int32)" />
<Member Name="Equals(System.ReadOnlySpan&lt;T&gt;)" />
<Member Name="Equals(System.Object)" />
<Member Name="DangerousCreate(System.Object,T@,System.Int32)" />
<Member Name="GetHashCode" />
<Member Name="TryCopyTo(System.Span&lt;T&gt;)" />
<Member Name="CopyTo(System.Span&lt;T&gt;)" />
</Type>
<Type Name="System.SpanExtensions" Condition="FEATURE_SPAN_OF_T">
<Member Name="AsBytes&lt;T&gt;(System.Span&lt;T&gt;)" />
Expand Down
85 changes: 80 additions & 5 deletions src/coreclr/src/mscorlib/src/System/ReadOnlySpan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;

#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'

namespace System
{
/// <summary>
Expand Down Expand Up @@ -124,6 +126,58 @@ internal ReadOnlySpan(ref T ptr, int length)
return ref _pointer.Value;
}

/// <summary>
/// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
/// <exception cref="System.NotSupportedException">
/// Always thrown by this method.
/// </exception>
/// </summary>
[Obsolete("Equals() on Span will always throw an exception. Use == instead.")]
public override bool Equals(object obj)
{
ThrowHelper.ThrowNotSupportedException_CannotCallEqualsOnSpan();
// Prevent compiler error CS0161: 'Span<T>.Equals(object)': not all code paths return a value
return default(bool);
}

/// <summary>
/// This method is not supported as spans cannot be boxed.
/// <exception cref="System.NotSupportedException">
/// Always thrown by this method.
/// </exception>
/// </summary>
[Obsolete("GetHashCode() on Span will always throw an exception.")]
public override int GetHashCode()
{
ThrowHelper.ThrowNotSupportedException_CannotCallGetHashCodeOnSpan();
// Prevent compiler error CS0161: 'Span<T>.GetHashCode()': not all code paths return a value
return default(int);
}

/// <summary>
/// Create a new read-only span over a portion of a regular managed object. This can be useful
/// if part of a managed object represents a "fixed array." This is dangerous because
/// "length" is not checked, nor is the fact that "rawPointer" actually lies within the object.
/// </summary>
/// <param name="obj">The managed object that contains the data to span over.</param>
/// <param name="objectData">A reference to data within that object.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
/// <exception cref="System.ArgumentNullException">
/// Thrown when the specified object is null.
/// </exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="length"/> is negative.
/// </exception>
public static ReadOnlySpan<T> DangerousCreate(object obj, ref T objectData, int length)
{
if (obj == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
if (length < 0)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);

return new ReadOnlySpan<T>(ref objectData, length);
}

/// <summary>
/// Defines an implicit conversion of a <see cref="Span{T}"/> to a <see cref="ReadOnlySpan{T}"/>
/// </summary>
Expand Down Expand Up @@ -238,13 +292,19 @@ public ReadOnlySpan<T> Slice(int start, int length)
}

/// <summary>
/// Checks to see if two spans point at the same memory. Note that
/// this does *not* check to see if the *contents* are equal.
/// Copies the contents of this read-only span into destination span. If the source
/// and destinations overlap, this method behaves as if the original values in
/// a temporary location before the destination is overwritten.
///
/// <param name="destination">The span to copy items into.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when the destination Span is shorter than the source Span.
/// </exception>
/// </summary>
public bool Equals(ReadOnlySpan<T> other)
public void CopyTo(Span<T> destination)
{
return (_length == other.Length) &&
(_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
if (!TryCopyTo(destination))
ThrowHelper.ThrowArgumentException_DestinationTooShort();
}

/// <summary>
Expand All @@ -260,6 +320,21 @@ public bool TryCopyTo(Span<T> destination)
SpanHelper.CopyTo<T>(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length);
return true;
}

/// <summary>
/// Returns true if left and right point at the same memory and have the same length. Note that
/// this does *not* check to see if the *contents* are equal.
/// </summary>
public static bool operator ==(ReadOnlySpan<T> left, ReadOnlySpan<T> right)
{
return left._length == right._length && Unsafe.AreSame<T>(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference());
}

/// <summary>
/// Returns false if left and right point at the same memory and have the same length. Note that
/// this does *not* check to see if the *contents* are equal.
/// </summary>
public static bool operator !=(ReadOnlySpan<T> left, ReadOnlySpan<T> right) => !(left == right);
}

public static class ReadOnlySpanExtensions
Expand Down
47 changes: 35 additions & 12 deletions src/coreclr/src/mscorlib/src/System/Span.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,31 @@ public unsafe Span(void* pointer, int length)
_length = length;
}

/// <summary>
/// Create a new span over a portion of a regular managed object. This can be useful
/// if part of a managed object represents a "fixed array." This is dangerous because
/// "length" is not checked, nor is the fact that "rawPointer" actually lies within the object.
/// </summary>
/// <param name="obj">The managed object that contains the data to span over.</param>
/// <param name="objectData">A reference to data within that object.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
/// <exception cref="System.ArgumentNullException">
/// Thrown when the specified object is null.
/// </exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="length"/> is negative.
/// </exception>
public static Span<T> DangerousCreate(object obj, ref T objectData, int length)
{
if (obj == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
if (length < 0)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);

return new Span<T>(ref objectData, length);
}


/// <summary>
/// An internal helper for creating spans.
/// </summary>
Expand Down Expand Up @@ -211,23 +236,16 @@ public bool TryCopyTo(Span<T> destination)
/// Returns true if left and right point at the same memory and have the same length. Note that
/// this does *not* check to see if the *contents* are equal.
/// </summary>
public static bool operator ==(Span<T> left, Span<T> right) => left.Equals(right);
public static bool operator ==(Span<T> left, Span<T> right)
{
return left._length == right._length && Unsafe.AreSame<T>(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference());
}

/// <summary>
/// Returns false if left and right point at the same memory and have the same length. Note that
/// this does *not* check to see if the *contents* are equal.
/// </summary>
public static bool operator !=(Span<T> left, Span<T> right) => !left.Equals(right);

/// <summary>
/// Checks to see if two spans point at the same memory. Note that
/// this does *not* check to see if the *contents* are equal.
/// </summary>
public bool Equals(Span<T> other)
{
return (_length == other.Length) &&
(_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
}
public static bool operator !=(Span<T> left, Span<T> right) => !(left == right);

/// <summary>
/// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
Expand Down Expand Up @@ -267,6 +285,11 @@ public override int GetHashCode()
/// </summary>
public static implicit operator Span<T>(ArraySegment<T> arraySegment) => new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);

/// <summary>
/// Defines an implicit conversion of a <see cref="Span{T}"/> to a <see cref="ReadOnlySpan{T}"/>
/// </summary>
public static implicit operator ReadOnlySpan<T>(Span<T> span) => new ReadOnlySpan<T>(ref span.DangerousGetPinnableReference(), span._length);

/// <summary>
/// Forms a slice out of the given span, beginning at 'start'.
/// </summary>
Expand Down

0 comments on commit 8170ac7

Please sign in to comment.