diff options
Diffstat (limited to 'Ryujinx.Common/Memory')
| -rw-r--r-- | Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs | 51 | ||||
| -rw-r--r-- | Ryujinx.Common/Memory/ByteMemoryPool.cs | 108 |
2 files changed, 159 insertions, 0 deletions
diff --git a/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs b/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs new file mode 100644 index 00000000..eda350bd --- /dev/null +++ b/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs @@ -0,0 +1,51 @@ +using System; +using System.Buffers; +using System.Threading; + +namespace Ryujinx.Common.Memory +{ + public sealed partial class ByteMemoryPool + { + /// <summary> + /// Represents a <see cref="IMemoryOwner{Byte}"/> that wraps an array rented from + /// <see cref="ArrayPool{Byte}.Shared"/> and exposes it as <see cref="Memory{Byte}"/> + /// with a length of the requested size. + /// </summary> + private sealed class ByteMemoryPoolBuffer : IMemoryOwner<byte> + { + private byte[] _array; + private readonly int _length; + + public ByteMemoryPoolBuffer(int length) + { + _array = ArrayPool<byte>.Shared.Rent(length); + _length = length; + } + + /// <summary> + /// Returns a <see cref="Memory{Byte}"/> belonging to this owner. + /// </summary> + public Memory<byte> Memory + { + get + { + byte[] array = _array; + + ObjectDisposedException.ThrowIf(array is null, this); + + return new Memory<byte>(array, 0, _length); + } + } + + public void Dispose() + { + var array = Interlocked.Exchange(ref _array, null); + + if (array != null) + { + ArrayPool<byte>.Shared.Return(array); + } + } + } + } +} diff --git a/Ryujinx.Common/Memory/ByteMemoryPool.cs b/Ryujinx.Common/Memory/ByteMemoryPool.cs new file mode 100644 index 00000000..2910f408 --- /dev/null +++ b/Ryujinx.Common/Memory/ByteMemoryPool.cs @@ -0,0 +1,108 @@ +using System; +using System.Buffers; + +namespace Ryujinx.Common.Memory +{ + /// <summary> + /// Provides a pool of re-usable byte array instances. + /// </summary> + public sealed partial class ByteMemoryPool + { + private static readonly ByteMemoryPool _shared = new ByteMemoryPool(); + + /// <summary> + /// Constructs a <see cref="ByteMemoryPool"/> instance. Private to force access through + /// the <see cref="ByteMemoryPool.Shared"/> instance. + /// </summary> + private ByteMemoryPool() + { + // No implementation + } + + /// <summary> + /// Retrieves a shared <see cref="ByteMemoryPool"/> instance. + /// </summary> + public static ByteMemoryPool Shared => _shared; + + /// <summary> + /// Returns the maximum buffer size supported by this pool. + /// </summary> + public int MaxBufferSize => Array.MaxLength; + + /// <summary> + /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>. + /// The buffer may contain data from a prior use. + /// </summary> + /// <param name="length">The buffer's required length in bytes</param> + /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> + /// <exception cref="ArgumentOutOfRangeException"></exception> + public IMemoryOwner<byte> Rent(long length) + => RentImpl(checked((int)length)); + + /// <summary> + /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>. + /// The buffer may contain data from a prior use. + /// </summary> + /// <param name="length">The buffer's required length in bytes</param> + /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> + /// <exception cref="ArgumentOutOfRangeException"></exception> + public IMemoryOwner<byte> Rent(ulong length) + => RentImpl(checked((int)length)); + + /// <summary> + /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>. + /// The buffer may contain data from a prior use. + /// </summary> + /// <param name="length">The buffer's required length in bytes</param> + /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> + /// <exception cref="ArgumentOutOfRangeException"></exception> + public IMemoryOwner<byte> Rent(int length) + => RentImpl(length); + + /// <summary> + /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>. + /// The buffer's contents are cleared (set to all 0s) before returning. + /// </summary> + /// <param name="length">The buffer's required length in bytes</param> + /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> + /// <exception cref="ArgumentOutOfRangeException"></exception> + public IMemoryOwner<byte> RentCleared(long length) + => RentCleared(checked((int)length)); + + /// <summary> + /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>. + /// The buffer's contents are cleared (set to all 0s) before returning. + /// </summary> + /// <param name="length">The buffer's required length in bytes</param> + /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> + /// <exception cref="ArgumentOutOfRangeException"></exception> + public IMemoryOwner<byte> RentCleared(ulong length) + => RentCleared(checked((int)length)); + + /// <summary> + /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>. + /// The buffer's contents are cleared (set to all 0s) before returning. + /// </summary> + /// <param name="length">The buffer's required length in bytes</param> + /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> + /// <exception cref="ArgumentOutOfRangeException"></exception> + public IMemoryOwner<byte> RentCleared(int length) + { + var buffer = RentImpl(length); + + buffer.Memory.Span.Clear(); + + return buffer; + } + + private static ByteMemoryPoolBuffer RentImpl(int length) + { + if ((uint)length > Array.MaxLength) + { + throw new ArgumentOutOfRangeException(nameof(length), length, null); + } + + return new ByteMemoryPoolBuffer(length); + } + } +} |
