Browse Source

Added optimized IMemoryGroup<T>.GetEnumerator() method

pull/1574/head
Sergio Pedri 6 years ago
parent
commit
a6e70a9c3e
  1. 10
      src/ImageSharp/Memory/DiscontiguousBuffers/IMemoryGroup{T}.cs
  2. 15
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs
  3. 23
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs
  4. 19
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs
  5. 16
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs

10
src/ImageSharp/Memory/DiscontiguousBuffers/IMemoryGroup{T}.cs

@ -33,5 +33,15 @@ namespace SixLabors.ImageSharp.Memory
/// the image buffers internally.
/// </remarks>
bool IsValid { get; }
/// <summary>
/// Returns a value-type implementing an allocation-free enumerator of the memory groups in the current
/// instance. The return type shouldn't be used directly: just use a <see langword="foreach"/> block on
/// the <see cref="IMemoryGroup{T}"/> instance in use and the C# compiler will automatically invoke this
/// method behind the scenes. This method takes precedence over the <see cref="IEnumerable{T}.GetEnumerator"/>
/// implementation, which is still available when casting to one of the underlying interfaces.
/// </summary>
/// <returns>A new <see cref="MemoryGroupEnumerator{T}"/> instance mapping the current <see cref="Memory{T}"/> values in use.</returns>
new MemoryGroupEnumerator<T> GetEnumerator();
}
}

15
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Memory
{
@ -37,6 +38,7 @@ namespace SixLabors.ImageSharp.Memory
public int Count
{
[MethodImpl(InliningOptions.ShortMethod)]
get
{
this.EnsureIsValid();
@ -73,7 +75,15 @@ namespace SixLabors.ImageSharp.Memory
}
}
public IEnumerator<Memory<T>> GetEnumerator()
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public MemoryGroupEnumerator<T> GetEnumerator()
{
return new MemoryGroupEnumerator<T>(this);
}
/// <inheritdoc/>
IEnumerator<Memory<T>> IEnumerable<Memory<T>>.GetEnumerator()
{
this.EnsureIsValid();
for (int i = 0; i < this.Count; i++)
@ -82,7 +92,8 @@ namespace SixLabors.ImageSharp.Memory
}
}
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<Memory<T>>)this).GetEnumerator();
internal void Invalidate()
{

23
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs

@ -3,13 +3,16 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Memory
{
internal abstract partial class MemoryGroup<T>
{
// Analogous to the "consumed" variant of MemorySource
private sealed class Consumed : MemoryGroup<T>
/// <summary>
/// A <see cref="MemoryGroup{T}"/> implementation that consumes the underlying memory buffers.
/// </summary>
public sealed class Consumed : MemoryGroup<T>, IEnumerable<Memory<T>>
{
private readonly Memory<T>[] source;
@ -20,11 +23,23 @@ namespace SixLabors.ImageSharp.Memory
this.View = new MemoryGroupView<T>(this);
}
public override int Count => this.source.Length;
public override int Count
{
[MethodImpl(InliningOptions.ShortMethod)]
get => this.source.Length;
}
public override Memory<T> this[int index] => this.source[index];
public override IEnumerator<Memory<T>> GetEnumerator()
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override MemoryGroupEnumerator<T> GetEnumerator()
{
return new MemoryGroupEnumerator<T>(this);
}
/// <inheritdoc/>
IEnumerator<Memory<T>> IEnumerable<Memory<T>>.GetEnumerator()
{
/* The runtime sees the Array class as if it implemented the
* type-generic collection interfaces explicitly, so here we

19
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs

@ -9,10 +9,12 @@ using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Memory
{
// Analogous to the "owned" variant of MemorySource
internal abstract partial class MemoryGroup<T>
{
private sealed class Owned : MemoryGroup<T>
/// <summary>
/// A <see cref="MemoryGroup{T}"/> implementation that owns the underlying memory buffers.
/// </summary>
public sealed class Owned : MemoryGroup<T>, IEnumerable<Memory<T>>
{
private IMemoryOwner<T>[] memoryOwners;
@ -30,6 +32,7 @@ namespace SixLabors.ImageSharp.Memory
public override int Count
{
[MethodImpl(InliningOptions.ShortMethod)]
get
{
this.EnsureNotDisposed();
@ -46,7 +49,15 @@ namespace SixLabors.ImageSharp.Memory
}
}
public override IEnumerator<Memory<T>> GetEnumerator()
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override MemoryGroupEnumerator<T> GetEnumerator()
{
return new MemoryGroupEnumerator<T>(this);
}
/// <inheritdoc/>
IEnumerator<Memory<T>> IEnumerable<Memory<T>>.GetEnumerator()
{
this.EnsureNotDisposed();
return this.memoryOwners.Select(mo => mo.Memory).GetEnumerator();
@ -70,7 +81,7 @@ namespace SixLabors.ImageSharp.Memory
this.IsValid = false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void EnsureNotDisposed()
{
if (this.memoryOwners is null)

16
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs

@ -6,7 +6,6 @@ using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory.Internals;
namespace SixLabors.ImageSharp.Memory
{
@ -48,10 +47,21 @@ namespace SixLabors.ImageSharp.Memory
public abstract void Dispose();
/// <inheritdoc />
public abstract IEnumerator<Memory<T>> GetEnumerator();
public abstract MemoryGroupEnumerator<T> GetEnumerator();
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
IEnumerator<Memory<T>> IEnumerable<Memory<T>>.GetEnumerator()
{
/* This method is implemented in each derived class.
* Implementing the method here as non-abstract and throwing,
* then reimplementing it explicitly in each derived class, is
* a workaround for the lack of support for abstract explicit
* interface method implementations in C#. */
throw new NotImplementedException($"The type {this.GetType()} needs to override IEnumerable<Memory<T>>.GetEnumerator()");
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<Memory<T>>)this).GetEnumerator();
/// <summary>
/// Creates a new memory group, allocating it's buffers with the provided allocator.

Loading…
Cancel
Save