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
}
}