PinnedArray.cs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #region Copyright and License
  2. /*
  3. This file is part of FFTW.NET, a wrapper around the FFTW library for the .NET framework.
  4. Copyright (C) 2017 Tobias Meyer
  5. License: Microsoft Reciprocal License (MS-RL)
  6. */
  7. #endregion
  8. using System;
  9. using System.Runtime.InteropServices;
  10. namespace FFTW.NET
  11. {
  12. /// <summary>
  13. /// Wrapper around <see cref="System.Array"/> which provides some level of type-safety.
  14. /// If you have access to the strongly typed instance of the underlying buffer (e.g. T[], T[,], T[,,], etc.)
  15. /// you should always get and set values using the strongly typed instance. <see cref="Array{T}"/>
  16. /// uses <see cref="Array.SetValue"/>/<see cref="Array.GetValue"/> internally which is much slower than
  17. /// using the strongly typed instance directly.
  18. /// </summary>
  19. public class PinnedArray<T> : IPinnedArray<T>
  20. where T : struct
  21. {
  22. readonly System.Array _buffer;
  23. readonly PinnedGCHandle _pin;
  24. public int Rank => _buffer.Rank;
  25. public Array Buffer => _buffer;
  26. public int Length => _buffer.Length;
  27. public IntPtr Pointer => _pin.Pointer;
  28. public bool IsDisposed => !_pin.IsAllocated;
  29. public PinnedArray(params int[] lengths)
  30. : this(Array.CreateInstance(typeof(T), lengths)) { }
  31. public PinnedArray(Array array)
  32. {
  33. if (array.GetType().GetElementType() != typeof(T))
  34. throw new ArgumentException($"Must have elements of type {typeof(T).FullName}.", nameof(array));
  35. _buffer = array;
  36. _pin = PinnedGCHandle.Pin(_buffer);
  37. }
  38. public int GetLength(int dimension) => _buffer.GetLength(dimension);
  39. public int[] GetSize()
  40. {
  41. int[] result = new int[Rank];
  42. for (int i = 0; i < Rank; i++)
  43. result[i] = GetLength(i);
  44. return result;
  45. }
  46. public T this[params int[] indices]
  47. {
  48. get { return (T)_buffer.GetValue(indices)!; }
  49. set { _buffer.SetValue(value, indices); }
  50. }
  51. public T this[int index]
  52. {
  53. get { return (T)_buffer.GetValue(index)!; }
  54. set { _buffer.SetValue(value, index); }
  55. }
  56. public T this[int i1, int i2]
  57. {
  58. get { return (T)_buffer.GetValue(i1, i2)!; }
  59. set { _buffer.SetValue(value, i1, i2); }
  60. }
  61. public T this[int i1, int i2, int i3]
  62. {
  63. get { return (T)_buffer.GetValue(i1, i2, i3)!; }
  64. set { _buffer.SetValue(value, i1, i2, i3); }
  65. }
  66. public static implicit operator Array(PinnedArray<T> array) => array._buffer;
  67. public static explicit operator PinnedArray<T>(Array array) => new PinnedArray<T>(array);
  68. public void Dispose() => _pin.Free();
  69. }
  70. }