mirror of https://github.com/SixLabors/ImageSharp
12 changed files with 270 additions and 7 deletions
@ -0,0 +1,15 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a group of one or more uniformly-sized discontinuous memory segments.
|
|||
/// The last segment can be smaller than the preceding ones.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The element type.</typeparam>
|
|||
public interface IUniformMemoryGroup<T> : IReadOnlyList<Memory<T>> where T : struct |
|||
{ |
|||
bool IsValid { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System; |
|||
|
|||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
|||
{ |
|||
public class InvalidMemoryOperationException : InvalidOperationException |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
using System; |
|||
using System.Buffers; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
|||
{ |
|||
/// <summary>
|
|||
/// Implements <see cref="IUniformMemoryGroup{T}"/>, defining a view for <see cref="UniformMemoryGroup{T}"/>
|
|||
/// rather than owning the segments.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This type provides an indirection, protecting the users of publicly exposed memory API-s
|
|||
/// from internal memory-swaps. Whenever an internal swap happens, the <see cref="UniformMemoryGroupView{T}"/>
|
|||
/// instance becomes invalid, throwing an exception on all operations.
|
|||
/// </remarks>
|
|||
/// <typeparam name="T">The element type.</typeparam>
|
|||
public class UniformMemoryGroupView<T> : IUniformMemoryGroup<T> where T : struct |
|||
{ |
|||
private readonly UniformMemoryGroup<T> owner; |
|||
private readonly MemoryOwnerWrapper[] memoryWrappers; |
|||
|
|||
public UniformMemoryGroupView(UniformMemoryGroup<T> owner) |
|||
{ |
|||
this.IsValid = true; |
|||
this.owner = owner; |
|||
this.memoryWrappers = new MemoryOwnerWrapper[owner.Count]; |
|||
|
|||
for (int i = 0; i < owner.Count; i++) |
|||
{ |
|||
this.memoryWrappers[i] = new MemoryOwnerWrapper(this, i); |
|||
} |
|||
} |
|||
|
|||
public IEnumerator<Memory<T>> GetEnumerator() => throw new NotImplementedException(); |
|||
|
|||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); |
|||
|
|||
public int Count { get; } |
|||
|
|||
public Memory<T> this[int index] => throw new NotImplementedException(); |
|||
|
|||
public bool IsValid { get; internal set; } |
|||
|
|||
class MemoryOwnerWrapper : MemoryManager<T> |
|||
{ |
|||
private UniformMemoryGroupView<T> view; |
|||
|
|||
private int index; |
|||
|
|||
public MemoryOwnerWrapper(UniformMemoryGroupView<T> view, int index) |
|||
{ |
|||
this.view = view; |
|||
this.index = index; |
|||
} |
|||
|
|||
protected override void Dispose(bool disposing) |
|||
{ |
|||
} |
|||
|
|||
public override Span<T> GetSpan() |
|||
{ |
|||
if (!this.view.IsValid) |
|||
{ |
|||
throw new InvalidOperationException(); |
|||
} |
|||
|
|||
return this.view[this.index].Span; |
|||
} |
|||
|
|||
public override MemoryHandle Pin(int elementIndex = 0) => throw new NotImplementedException(); |
|||
|
|||
public override void Unpin() => throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
using System; |
|||
using System.Buffers; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
|||
{ |
|||
public abstract partial class UniformMemoryGroup<T> |
|||
{ |
|||
private class Allocated : UniformMemoryGroup<T> |
|||
{ |
|||
private IMemoryOwner<T>[] memoryOwners; |
|||
|
|||
public Allocated(IMemoryOwner<T>[] memoryOwners) |
|||
{ |
|||
this.memoryOwners = memoryOwners; |
|||
} |
|||
|
|||
public override IEnumerator<Memory<T>> GetEnumerator() |
|||
{ |
|||
this.EnsureNotDisposed(); |
|||
return this.memoryOwners.Select(mo => mo.Memory).GetEnumerator(); |
|||
} |
|||
|
|||
|
|||
public override int Count |
|||
{ |
|||
get |
|||
{ |
|||
this.EnsureNotDisposed(); |
|||
return this.memoryOwners.Length; |
|||
} |
|||
} |
|||
|
|||
public override Memory<T> this[int index] |
|||
{ |
|||
get |
|||
{ |
|||
this.EnsureNotDisposed(); |
|||
return this.memoryOwners[index].Memory; |
|||
} |
|||
} |
|||
|
|||
public override void Dispose() |
|||
{ |
|||
if (this.memoryOwners == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
foreach (IMemoryOwner<T> memoryOwner in this.memoryOwners) |
|||
{ |
|||
memoryOwner.Dispose(); |
|||
} |
|||
|
|||
this.memoryOwners = null; |
|||
this.IsValid = false; |
|||
} |
|||
|
|||
private void EnsureNotDisposed() |
|||
{ |
|||
if (this.memoryOwners == null) |
|||
{ |
|||
throw new ObjectDisposedException(nameof(UniformMemoryGroup<T>)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
|||
{ |
|||
public abstract partial class UniformMemoryGroup<T> |
|||
{ |
|||
private class External : UniformMemoryGroup<T> |
|||
{ |
|||
private readonly ReadOnlyMemory<Memory<T>> source; |
|||
|
|||
public External(ReadOnlyMemory<Memory<T>> source) |
|||
{ |
|||
// TODO: sizes should be uniform, validate!
|
|||
|
|||
this.source = source; |
|||
} |
|||
|
|||
public override IEnumerator<Memory<T>> GetEnumerator() |
|||
{ |
|||
for (int i = 0; i < this.source.Length; i++) |
|||
{ |
|||
yield return this.source.Span[i]; |
|||
} |
|||
} |
|||
|
|||
public override int Count => this.source.Length; |
|||
|
|||
public override Memory<T> this[int index] => this.source.Span[index]; |
|||
|
|||
public override void Dispose() |
|||
{ |
|||
// No ownership nothing to dispose
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a group of one or more uniformly-sized discontinuous memory segments, owned by this instance.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The element type.</typeparam>
|
|||
public abstract partial class UniformMemoryGroup<T> : IUniformMemoryGroup<T>, IDisposable where T : struct |
|||
{ |
|||
public abstract IEnumerator<Memory<T>> GetEnumerator(); |
|||
|
|||
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); |
|||
|
|||
public abstract int Count { get; } |
|||
|
|||
public abstract Memory<T> this[int index] { get; } |
|||
|
|||
public abstract void Dispose(); |
|||
|
|||
public bool IsValid { get; protected set; } |
|||
|
|||
public static UniformMemoryGroup<T> Allocate(MemoryAllocator allocator, long length) |
|||
{ |
|||
long bufferCount = length / allocator.GetMaximumContiguousBufferLength(); |
|||
|
|||
// TODO: Allocate bufferCount buffers
|
|||
throw new NotImplementedException(); |
|||
} |
|||
|
|||
public static UniformMemoryGroup<T> Wrap(params Memory<T>[] source) => Wrap(source.AsMemory()); |
|||
|
|||
public static UniformMemoryGroup<T> Wrap(ReadOnlyMemory<Memory<T>> source) |
|||
{ |
|||
return new External(source); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue