using Microsoft.ML.OnnxRuntime.Tensors; using System; using System.Buffers; using System.Diagnostics; namespace Microsoft.ML.OnnxRuntime { /// /// Represents an Onnx Value with its underlying buffer pinned /// public class FixedBufferOnnxValue : IDisposable { internal MemoryHandle PinnedMemory { get; private set; } internal IntPtr Value { get; private set; } internal OnnxValueType OnnxValueType { get; private set; } internal TensorElementType ElementType { get; private set; } private FixedBufferOnnxValue(MemoryHandle pinnedMemory, IntPtr onnxValue, OnnxValueType onnxValueType, TensorElementType elementType) { PinnedMemory = pinnedMemory; Value = onnxValue; OnnxValueType = onnxValueType; ElementType = elementType; } /// /// Creates a object from the tensor and pins its underlying buffer. /// /// /// /// public static FixedBufferOnnxValue CreateFromTensor(Tensor value) { if (value is Tensor) { throw new ArgumentException("Only numeric tensors can be used to create FixedBufferOnnxValue.", nameof(value)); } NativeOnnxValueHelper.CreateNativeOnnxValue(value, out IntPtr onnxValue, out MemoryHandle pinnedMemoryHandle, out OnnxValueType onnxValueType, out TensorElementType elementType); Debug.Assert( onnxValueType == OnnxValueType.ONNX_TYPE_TENSOR && elementType != TensorElementType.String, "the value should always be a numeric tensor"); return new FixedBufferOnnxValue(pinnedMemoryHandle, onnxValue, onnxValueType, elementType); } #region IDisposable Support // standard dispose pattern to deal with both managed and native resources private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { ((IDisposable)PinnedMemory).Dispose(); } if (Value != IntPtr.Zero) { NativeMethods.OrtReleaseValue(Value); Value = IntPtr.Zero; } disposed = true; } } ~FixedBufferOnnxValue() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } }