diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.cs b/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.cs
index 859e543e7b..18b6977394 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/DisposableNamedOnnxValue.cs
@@ -55,6 +55,7 @@ namespace Microsoft.ML.OnnxRuntime
private NativeMemoryHandler _nativeMemoryManager;
private TensorElementType _elementType;
private OnnxValueType _onnxValueType;
+ private bool _disposed = false;
private DisposableNamedOnnxValue(string name, Object value, OnnxValueType onnxValueType, TensorElementType elementType, NativeMemoryHandler nativeMemoryManager)
: base(name, value)
@@ -264,15 +265,21 @@ namespace Microsoft.ML.OnnxRuntime
protected virtual void Dispose(bool disposing)
{
+ if(_disposed)
+ {
+ return;
+ }
+
+ // dispose managed state (managed objects).
if (disposing)
{
- // dispose managed state (managed objects).
if (_nativeMemoryManager != null)
{
_nativeMemoryManager.Dispose();
_nativeMemoryManager = null;
}
}
+ _disposed = true;
}
public void Dispose()
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.cs b/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.cs
index 8ef1fc119f..4444ed85e6 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/FixedBufferOnnxValue.cs
@@ -9,6 +9,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public class FixedBufferOnnxValue : IDisposable
{
+ private bool _disposed = false;
internal MemoryHandle PinnedMemory { get; private set; }
internal OrtValue Value { get; private set; }
internal OnnxValueType OnnxValueType { get; private set; }
@@ -46,11 +47,17 @@ namespace Microsoft.ML.OnnxRuntime
protected virtual void Dispose(bool disposing)
{
+ if(_disposed)
+ {
+ return;
+ }
+
if (disposing)
{
Value.Dispose();
PinnedMemory.Dispose();
}
+ _disposed = true;
}
public void Dispose()
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.cs b/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.cs
index a7b50003ef..a54e6c0f51 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.cs
@@ -21,6 +21,7 @@ namespace Microsoft.ML.OnnxRuntime
private SessionOptions _builtInSessionOptions = null;
private RunOptions _builtInRunOptions = null;
private ModelMetadata _modelMetadata = null;
+ private bool _disposed = false;
#region Public API
@@ -902,27 +903,43 @@ namespace Microsoft.ML.OnnxRuntime
#endregion
- #region IDisposable/ no finalizers needed
+ #region IDisposable
+
+ ///
+ /// Finalizer. to cleanup session in case it runs
+ /// and the user forgets to Dispose() of the session
+ ///
+ ~InferenceSession()
+ {
+ Dispose(false);
+ }
public void Dispose()
{
- GC.SuppressFinalize(this);
Dispose(true);
+ GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
+ if(_disposed)
+ {
+ return;
+ }
+
if (disposing)
{
// cleanup managed resources
if (_builtInSessionOptions != null)
{
_builtInSessionOptions.Dispose();
+ _builtInSessionOptions = null;
}
if (_builtInRunOptions != null)
{
_builtInRunOptions.Dispose();
+ _builtInRunOptions = null;
}
}
@@ -930,11 +947,12 @@ namespace Microsoft.ML.OnnxRuntime
if (_nativeHandle != IntPtr.Zero)
{
NativeMethods.OrtReleaseSession(_nativeHandle);
+ _nativeHandle = IntPtr.Zero;
}
+ _disposed = true;
}
#endregion
-
}
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeApiStatus.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeApiStatus.cs
index dabe0b4d68..bbd961309a 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeApiStatus.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeApiStatus.cs
@@ -10,9 +10,9 @@ namespace Microsoft.ML.OnnxRuntime
{
private static string GetErrorMessage(IntPtr /*(ONNXStatus*)*/status)
{
+ // nativeString belongs to status, no need for separate release
IntPtr nativeString = NativeMethods.OrtGetErrorMessage(status);
- string str = Marshal.PtrToStringAnsi(nativeString); //assumes charset = ANSI
- return str;
+ return NativeOnnxValueHelper.StringFromNativeUtf8(nativeString);
}
///
@@ -25,10 +25,16 @@ namespace Microsoft.ML.OnnxRuntime
{
if (nativeStatus != IntPtr.Zero)
{
- ErrorCode statusCode = NativeMethods.OrtGetErrorCode(nativeStatus);
- string errorMessage = GetErrorMessage(nativeStatus);
- NativeMethods.OrtReleaseStatus(nativeStatus);
- throw new OnnxRuntimeException(statusCode, errorMessage);
+ try
+ {
+ ErrorCode statusCode = NativeMethods.OrtGetErrorCode(nativeStatus);
+ string errorMessage = GetErrorMessage(nativeStatus);
+ throw new OnnxRuntimeException(statusCode, errorMessage);
+ }
+ finally
+ {
+ NativeMethods.OrtReleaseStatus(nativeStatus);
+ }
}
}
}
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxTensorMemory.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxTensorMemory.cs
index 4c1958485f..b62ac98a2b 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxTensorMemory.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxTensorMemory.cs
@@ -21,7 +21,6 @@ namespace Microsoft.ML.OnnxRuntime
internal class NativeOnnxTensorMemory : MemoryManager, NativeMemoryHandler
{
private bool _disposed;
- private int _referenceCount;
private IntPtr _onnxValueHandle; // pointer to onnxvalue object in native
private IntPtr _dataBufferPointer; // pointer to mutable tensor data in native memory
private string[] _dataBufferAsString; // string tensor values copied into managed memory
@@ -35,6 +34,7 @@ namespace Microsoft.ML.OnnxRuntime
Type type = null;
int width = 0;
_onnxValueHandle = onnxValueHandle;
+ _disposed = false;
IntPtr typeAndShape = IntPtr.Zero;
NativeApiStatus.VerifySuccess(NativeMethods.OrtGetTensorTypeAndShape(onnxValueHandle, out typeAndShape));
try
@@ -119,16 +119,8 @@ namespace Microsoft.ML.OnnxRuntime
public IntPtr Handle { get { return _onnxValueHandle; } }
- public void Dispose()
- {
- GC.SuppressFinalize(this);
- Dispose(true);
- }
-
public bool IsDisposed => _disposed;
- protected bool IsRetained => _referenceCount > 0;
-
public int[] Dimensions => _dimensions;
public int Rank => _dimensions.Length;
@@ -172,53 +164,35 @@ namespace Microsoft.ML.OnnxRuntime
{
throw new ArgumentOutOfRangeException(nameof(elementIndex));
}
- Retain();
-
return new MemoryHandle((void*)((int)_dataBufferPointer + elementIndex * _elementWidth)); //could not use Unsafe.Add
}
}
- public override void Unpin()
+ // MemoryHandle returned above by Pin() should be disposed.
+ // Unpin() is purely to satisfy the interface.
+ // TODO: This class needs work. It is not clear what happens
+ // if the MemoryHandle remains alive and this class gets Disposed.
+ public override void Unpin() { }
+
+ public void Dispose()
{
- Release();
- }
-
- private bool Release()
- {
- int newRefCount = Interlocked.Decrement(ref _referenceCount);
-
- if (newRefCount < 0)
- {
- throw new InvalidOperationException("Unmatched Release/Retain");
- }
-
- return newRefCount != 0;
- }
-
- private void Retain()
- {
- if (IsDisposed)
- {
- throw new ObjectDisposedException(nameof(NativeOnnxTensorMemory));
- }
-
- Interlocked.Increment(ref _referenceCount);
+ Dispose(true);
+ GC.SuppressFinalize(this);
}
protected override void Dispose(bool disposing)
{
- if (_disposed)
+ if(_disposed)
{
return;
}
- if (disposing)
+ if (_onnxValueHandle != IntPtr.Zero)
{
- // do managed objects cleanup
+ NativeMethods.OrtReleaseValue(_onnxValueHandle);
+ _onnxValueHandle = IntPtr.Zero;
}
- NativeMethods.OrtReleaseValue(_onnxValueHandle);
-
_disposed = true;
}
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OnnxRuntime.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OnnxRuntime.cs
index d0091f6cbe..a4bf08d3ba 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/OnnxRuntime.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/OnnxRuntime.cs
@@ -51,31 +51,13 @@ namespace Microsoft.ML.OnnxRuntime
private OnnxRuntime() //Problem: it is not possible to pass any option for a Singleton
:base(IntPtr.Zero, true)
{
- handle = IntPtr.Zero;
- try
- {
- NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateEnv(LogLevel.Warning, @"CSharpOnnxRuntime", out handle));
- }
- catch (OnnxRuntimeException e)
- {
- if (handle != IntPtr.Zero)
- {
- Delete(handle);
- handle = IntPtr.Zero;
- }
- throw e;
- }
-
- }
-
- private static void Delete(IntPtr nativePtr)
- {
- NativeMethods.OrtReleaseEnv(nativePtr);
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateEnv(LogLevel.Warning, @"CSharpOnnxRuntime", out handle));
}
protected override bool ReleaseHandle()
{
- Delete(handle);
+ NativeMethods.OrtReleaseEnv(handle);
+ handle = IntPtr.Zero;
return true;
}
}
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.cs
index 426a4445e1..0f610d2a23 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.cs
@@ -37,10 +37,9 @@ namespace Microsoft.ML.OnnxRuntime
/// to pre-allocated memory. In that case, the instance of OrtMemoryInfo contains the information about the allocator
/// used to allocate the underlying memory.
///
- public class OrtMemoryInfo : IDisposable
+ public class OrtMemoryInfo : SafeHandle
{
private static readonly Lazy _defaultCpuAllocInfo = new Lazy(CreateCpuMemoryInfo);
- private IntPtr _pointer;
private readonly bool _owned; // false if we are exposing OrtMemoryInfo from an allocator which owns it
private static OrtMemoryInfo CreateCpuMemoryInfo()
@@ -66,10 +65,12 @@ namespace Microsoft.ML.OnnxRuntime
{
get
{
- return _pointer;
+ return handle;
}
}
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
+
///
/// This allocator takes an native pointer to already existing
/// instance of OrtMemoryInfo. That instance may either be owned or not
@@ -78,8 +79,8 @@ namespace Microsoft.ML.OnnxRuntime
///
///
internal OrtMemoryInfo(IntPtr allocInfo, bool owned)
+ : base(allocInfo, true)
{
- _pointer = allocInfo;
_owned = owned;
}
@@ -100,6 +101,7 @@ namespace Microsoft.ML.OnnxRuntime
/// Device id
/// Memory type
public OrtMemoryInfo(byte[] utf8AllocatorName, OrtAllocatorType allocatorType, int deviceId, OrtMemType memoryType)
+ : base(IntPtr.Zero, true)
{
using (var pinnedName = new PinnedGCHandle(GCHandle.Alloc(utf8AllocatorName, GCHandleType.Pinned)))
{
@@ -107,7 +109,7 @@ namespace Microsoft.ML.OnnxRuntime
allocatorType,
deviceId,
memoryType,
- out _pointer));
+ out handle));
}
_owned = true;
}
@@ -132,7 +134,7 @@ namespace Microsoft.ML.OnnxRuntime
get
{
IntPtr utf8Name = IntPtr.Zero;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetName(_pointer, out utf8Name));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetName(handle, out utf8Name));
return NativeOnnxValueHelper.StringFromNativeUtf8(utf8Name);
}
}
@@ -145,7 +147,7 @@ namespace Microsoft.ML.OnnxRuntime
get
{
int id = 0;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetId(_pointer, out id));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetId(handle, out id));
return id;
}
}
@@ -159,7 +161,7 @@ namespace Microsoft.ML.OnnxRuntime
public OrtMemType GetMemoryType()
{
OrtMemType memoryType = OrtMemType.Default;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetMemType(_pointer, out memoryType));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetMemType(handle, out memoryType));
return memoryType;
}
@@ -170,7 +172,7 @@ namespace Microsoft.ML.OnnxRuntime
public OrtAllocatorType GetAllocatorType()
{
OrtAllocatorType allocatorType = OrtAllocatorType.ArenaAllocator;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetType(_pointer, out allocatorType));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtMemoryInfoGetType(handle, out allocatorType));
return allocatorType;
}
@@ -191,7 +193,7 @@ namespace Microsoft.ML.OnnxRuntime
return true;
}
int result = -1;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtCompareMemoryInfo(_pointer, other._pointer, out result));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtCompareMemoryInfo(handle, other.Pointer, out result));
return (result == 0);
}
@@ -200,25 +202,19 @@ namespace Microsoft.ML.OnnxRuntime
return Pointer.ToInt32();
}
- #region IDisposable Support
- protected virtual void Dispose(bool disposing)
+ #region SafeHandle
+ protected override bool ReleaseHandle()
{
- if (disposing)
+ // If this instance exposes OrtMemoryInfo that belongs
+ // to the allocator then the allocator owns it
+ if (_owned)
{
- if (_owned)
- {
- NativeMethods.OrtReleaseMemoryInfo(_pointer);
- }
- _pointer = IntPtr.Zero;
+ NativeMethods.OrtReleaseMemoryInfo(handle);
}
+ handle = IntPtr.Zero;
+ return true;
}
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- // We intentionally do not provider an finalizer for the class
#endregion
}
@@ -230,8 +226,11 @@ namespace Microsoft.ML.OnnxRuntime
/// lifespan of the allocation. Or, if you prefer, all OrtMemoryAllocation instances must be
/// disposed of before the corresponding allocator instances are disposed of.
///
- public class OrtMemoryAllocation : IDisposable
+ public class OrtMemoryAllocation : SafeHandle
{
+ // This allocator is used to free this allocation
+ // This also prevents OrtAllocator GC/finalization in case
+ // the user forgets to Dispose() of this allocation
private OrtAllocator _allocator;
///
@@ -245,16 +244,18 @@ namespace Microsoft.ML.OnnxRuntime
///
///
internal OrtMemoryAllocation(OrtAllocator allocator, IntPtr pointer, uint size)
+ : base(pointer, true)
{
_allocator = allocator;
- Pointer = pointer;
Size = size;
}
///
/// Internal accessor to call native methods
///
- internal IntPtr Pointer { get; private set; }
+ internal IntPtr Pointer { get { return handle; } }
+
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
///
/// Returns the size of the allocation
@@ -268,24 +269,14 @@ namespace Microsoft.ML.OnnxRuntime
return _allocator.Info;
}
}
- #region IDisposable Support
- protected virtual void Dispose(bool disposing)
+ #region SafeHandle
+ protected override bool ReleaseHandle()
{
- if (disposing)
- {
- if (_allocator != null)
- {
- _allocator.FreeMemory(Pointer);
- }
- Pointer = IntPtr.Zero;
- }
+ _allocator.FreeMemory(handle);
+ handle = IntPtr.Zero;
+ return true;
}
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
#endregion
}
@@ -294,10 +285,9 @@ namespace Microsoft.ML.OnnxRuntime
/// This allocator enables you to allocate memory from the internal
/// memory pools including device allocations. Useful for binding.
///
- public class OrtAllocator : IDisposable
+ public class OrtAllocator : SafeHandle
{
private static readonly Lazy _defaultInstance = new Lazy(GetDefaultCpuAllocator);
- private IntPtr _pointer;
private readonly bool _owned;
private static OrtAllocator GetDefaultCpuAllocator()
@@ -324,19 +314,21 @@ namespace Microsoft.ML.OnnxRuntime
{
get
{
- return _pointer;
+ return handle;
}
}
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
+
///
/// Internal constructor wraps existing native allocators
///
///
///
internal OrtAllocator(IntPtr allocator, bool owned)
+ : base(allocator, true)
{
- this._pointer = allocator;
- this._owned = owned;
+ _owned = owned;
}
///
@@ -348,8 +340,9 @@ namespace Microsoft.ML.OnnxRuntime
///
///
public OrtAllocator(InferenceSession session, OrtMemoryInfo memInfo)
+ : base(IntPtr.Zero, true)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateAllocator(session.Handle, memInfo.Pointer, out _pointer));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateAllocator(session.Handle, memInfo.Pointer, out handle));
_owned = true;
}
@@ -361,7 +354,7 @@ namespace Microsoft.ML.OnnxRuntime
get
{
IntPtr memoryInfo = IntPtr.Zero;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtAllocatorGetInfo(_pointer, out memoryInfo));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtAllocatorGetInfo(handle, out memoryInfo));
// This serves as an exposure of memory_info owned by the allocator
return new OrtMemoryInfo(memoryInfo, false);
}
@@ -375,7 +368,7 @@ namespace Microsoft.ML.OnnxRuntime
public OrtMemoryAllocation Allocate(uint size)
{
IntPtr allocation = IntPtr.Zero;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtAllocatorAlloc(_pointer, (UIntPtr)size, out allocation));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtAllocatorAlloc(handle, (UIntPtr)size, out allocation));
return new OrtMemoryAllocation(this, allocation, size);
}
@@ -385,29 +378,21 @@ namespace Microsoft.ML.OnnxRuntime
///
internal void FreeMemory(IntPtr allocation)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtAllocatorFree(_pointer, allocation));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtAllocatorFree(handle, allocation));
}
- #region IDisposable Support
- protected virtual void Dispose(bool disposing)
+ #region SafeHandle
+ protected override bool ReleaseHandle()
{
- if (disposing)
+ // Singleton default allocator is not owned
+ if (_owned)
{
- if (_owned)
- {
- NativeMethods.OrtReleaseAllocator(_pointer);
- }
- _pointer = IntPtr.Zero;
+ NativeMethods.OrtReleaseAllocator(handle);
}
+ handle = IntPtr.Zero;
+ return true;
}
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- // We intentionally do not provider an finalizer for the class
#endregion
}
}
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.cs
index 364a5ea21c..92ce948251 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtIoBinding.cs
@@ -14,27 +14,28 @@ namespace Microsoft.ML.OnnxRuntime
/// that piece of memory to an input name and shape and onnxruntime will use that as input.
/// Other traditional inputs can also be bound that already exists as Tensors
///
- public class OrtIoBinding : IDisposable
+ public class OrtIoBinding : SafeHandle
{
- private IntPtr _handle;
-
///
/// Use InferenceSession.CreateIoBinding()
///
///
internal OrtIoBinding(InferenceSession session)
+ : base(IntPtr.Zero, true)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateIoBinding(session.Handle, out _handle));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateIoBinding(session.Handle, out handle));
}
internal IntPtr Handle
{
get
{
- return _handle;
+ return handle;
}
}
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
+
///
/// Bind a piece of pre-allocated native memory as a OrtValue Tensor with a given shape
/// to an input with a given name. The model will read the specified input from that memory
@@ -114,7 +115,7 @@ namespace Microsoft.ML.OnnxRuntime
{
var utf8NamePinned = GCHandle.Alloc(NativeOnnxValueHelper.StringToZeroTerminatedUtf8(name), GCHandleType.Pinned);
using (var pinnedName = new PinnedGCHandle(utf8NamePinned))
- NativeApiStatus.VerifySuccess(NativeMethods.OrtBindOutputToDevice(_handle, pinnedName.Pointer, memInfo.Pointer));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtBindOutputToDevice(handle, pinnedName.Pointer, memInfo.Pointer));
}
///
@@ -130,11 +131,11 @@ namespace Microsoft.ML.OnnxRuntime
{
if (isInput)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtBindInput(_handle, pinnedName.Pointer, ortValue));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtBindInput(handle, pinnedName.Pointer, ortValue));
}
else
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtBindOutput(_handle, pinnedName.Pointer, ortValue));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtBindOutput(handle, pinnedName.Pointer, ortValue));
}
}
}
@@ -149,7 +150,7 @@ namespace Microsoft.ML.OnnxRuntime
IntPtr lengths = IntPtr.Zero;
UIntPtr count = UIntPtr.Zero;
var allocator = OrtAllocator.DefaultInstance;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtGetBoundOutputNames(_handle, allocator.Pointer, out buffer, out lengths, out count));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtGetBoundOutputNames(handle, allocator.Pointer, out buffer, out lengths, out count));
if(count.Equals(UIntPtr.Zero))
{
@@ -193,7 +194,7 @@ namespace Microsoft.ML.OnnxRuntime
IntPtr ortValues = IntPtr.Zero;
UIntPtr count = UIntPtr.Zero;
var allocator = OrtAllocator.DefaultInstance;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtGetBoundOutputValues(_handle, allocator.Pointer, out ortValues, out count));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtGetBoundOutputValues(handle, allocator.Pointer, out ortValues, out count));
if(count.Equals(UIntPtr.Zero))
{
@@ -225,7 +226,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void ClearBoundInputs()
{
- NativeMethods.OrtClearBoundInputs(_handle);
+ NativeMethods.OrtClearBoundInputs(handle);
}
///
@@ -233,25 +234,17 @@ namespace Microsoft.ML.OnnxRuntime
///
public void ClearBoundOutputs()
{
- NativeMethods.OrtClearBoundOutputs(_handle);
+ NativeMethods.OrtClearBoundOutputs(handle);
}
- #region Disposable Support
- protected virtual void Dispose(bool disposing)
+ #region SafeHandle
+ protected override bool ReleaseHandle()
{
- if(disposing)
- {
- NativeMethods.OrtReleaseIoBinding(_handle);
- _handle = IntPtr.Zero;
- }
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
+ NativeMethods.OrtReleaseIoBinding(handle);
+ handle = IntPtr.Zero;
+ return true;
}
- // No need for the finalizer
#endregion
}
}
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.cs
index 5c097eccd7..92c8896b82 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.cs
@@ -22,20 +22,24 @@ namespace Microsoft.ML.OnnxRuntime
///
/// Represents a disposable OrtValue
///
- public class OrtValue : IDisposable
+ public class OrtValue : SafeHandle
{
///
/// Use factory methods to instantiate
///
///
- /// Default true, own the raw handle
+ /// Default true, own the raw handle
+ /// However, we use this class to expose OrtValue that is owned by DisposableNamedOnnxValue
+ ///
internal OrtValue(IntPtr handle, bool owned = true)
+ : base(handle, true)
{
- Handle = handle;
IsOwned = owned;
}
- internal IntPtr Handle { get; private set; }
+ internal IntPtr Handle { get { return handle; } }
+
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
#region NamedOnnxValue/DisposableOnnxValue accommodations
@@ -54,10 +58,10 @@ namespace Microsoft.ML.OnnxRuntime
///
internal IntPtr Disown()
{
- var handle = Handle;
- Handle = IntPtr.Zero;
+ var ret = Handle;
+ handle = IntPtr.Zero;
IsOwned = false;
- return handle;
+ return ret;
}
internal bool IsOwned { get; private set; }
@@ -337,28 +341,18 @@ namespace Microsoft.ML.OnnxRuntime
return ortValue;
}
- #region Disposable Support
- protected virtual void Dispose(bool disposing)
+ #region SafeHandle
+ protected override bool ReleaseHandle()
{
- if (disposing)
+ // We have to surrender ownership to some legacy classes
+ // Or we never had that ownership to begin with
+ if (IsOwned)
{
- // We have to surrender ownership to some legacy classes
- // Or we never had that ownership to begin with
- if (Handle != IntPtr.Zero)
- {
- if (IsOwned)
- {
- NativeMethods.OrtReleaseValue(Handle);
- }
- // Prevent use after disposal
- Handle = IntPtr.Zero;
- }
+ NativeMethods.OrtReleaseValue(handle);
}
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
+ // Prevent use after disposal
+ handle = IntPtr.Zero;
+ return true;
}
// No need for the finalizer
#endregion
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/RunOptions.cs b/csharp/src/Microsoft.ML.OnnxRuntime/RunOptions.cs
index 3bd35e3f94..ed2e8cebee 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/RunOptions.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/RunOptions.cs
@@ -6,23 +6,25 @@ using System.Runtime.InteropServices;
namespace Microsoft.ML.OnnxRuntime
{
/// Sets various runtime options.
- public class RunOptions : IDisposable
+ public class RunOptions : SafeHandle
{
- private IntPtr _nativePtr;
internal IntPtr Handle
{
get
{
- return _nativePtr;
+ return handle;
}
}
- public RunOptions()
+ public RunOptions()
+ :base(IntPtr.Zero, true)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateRunOptions(out _nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateRunOptions(out handle));
}
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
+
///
/// Log Severity Level for the session logs. Default = ORT_LOGGING_LEVEL_WARNING
///
@@ -34,7 +36,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetRunLogSeverityLevel(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetRunLogSeverityLevel(handle, value));
_logSeverityLevel = value;
}
}
@@ -52,7 +54,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetRunLogVerbosityLevel(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetRunLogVerbosityLevel(handle, value));
_logVerbosityLevel = value;
}
}
@@ -67,14 +69,14 @@ namespace Microsoft.ML.OnnxRuntime
{
string tag = null;
IntPtr tagPtr = IntPtr.Zero;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsGetRunTag(_nativePtr, out tagPtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsGetRunTag(handle, out tagPtr));
tag = Marshal.PtrToStringAnsi(tagPtr); // assume ANSI string
// should not release the memory of the tagPtr, because it returns the c_str() of the std::string being used inside RunOptions C++ class
return tag;
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetRunTag(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetRunTag(handle, value));
}
}
@@ -93,12 +95,12 @@ namespace Microsoft.ML.OnnxRuntime
{
if (!_terminate && value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetTerminate(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsSetTerminate(handle));
_terminate = true;
}
else if (_terminate && !value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsUnsetTerminate(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtRunOptionsUnsetTerminate(handle));
_terminate = false;
}
}
@@ -106,21 +108,13 @@ namespace Microsoft.ML.OnnxRuntime
private bool _terminate = false; //value set to default value of the C++ RunOptions
- #region IDisposable
+ #region SafeHandle
- public void Dispose()
+ protected override bool ReleaseHandle()
{
- GC.SuppressFinalize(this);
- Dispose(true);
- }
-
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- NativeMethods.OrtReleaseRunOptions(_nativePtr);
- }
+ NativeMethods.OrtReleaseRunOptions(handle);
+ handle = IntPtr.Zero;
+ return true;
}
#endregion
diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.cs b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.cs
index b04a7e4fec..16ff02aed0 100644
--- a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.cs
+++ b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.cs
@@ -34,9 +34,8 @@ namespace Microsoft.ML.OnnxRuntime
///
/// Holds the options for creating an InferenceSession
///
- public class SessionOptions : IDisposable
+ public class SessionOptions : SafeHandle
{
- private IntPtr _nativePtr;
private static string[] cudaDelayLoadedLibs = { "cublas64_10.dll", "cudnn64_7.dll", "curand64_10.dll" };
#region Constructor and Factory methods
@@ -45,8 +44,9 @@ namespace Microsoft.ML.OnnxRuntime
/// Constructs an empty SessionOptions
///
public SessionOptions()
+ :base(IntPtr.Zero, true)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateSessionOptions(out _nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateSessionOptions(out handle));
}
///
@@ -69,8 +69,8 @@ namespace Microsoft.ML.OnnxRuntime
{
CheckCudaExecutionProviderDLLs();
SessionOptions options = new SessionOptions();
- NativeMethods.OrtSessionOptionsAppendExecutionProvider_CUDA(options._nativePtr, deviceId);
- NativeMethods.OrtSessionOptionsAppendExecutionProvider_CPU(options._nativePtr, 1);
+ NativeMethods.OrtSessionOptionsAppendExecutionProvider_CUDA(options.Handle, deviceId);
+ NativeMethods.OrtSessionOptionsAppendExecutionProvider_CPU(options.Handle, 1);
return options;
}
@@ -83,7 +83,7 @@ namespace Microsoft.ML.OnnxRuntime
public static SessionOptions MakeSessionOptionWithNupharProvider(String settings = "")
{
SessionOptions options = new SessionOptions();
- NativeMethods.OrtSessionOptionsAppendExecutionProvider_Nuphar(options._nativePtr, 1, settings);
+ NativeMethods.OrtSessionOptionsAppendExecutionProvider_Nuphar(options.Handle, 1, settings);
return options;
}
@@ -92,7 +92,7 @@ namespace Microsoft.ML.OnnxRuntime
#region ExecutionProviderAppends
public void AppendExecutionProvider_CPU(int useArena)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_CPU(_nativePtr, useArena));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_CPU(handle, useArena));
}
///
@@ -100,7 +100,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_Dnnl(int useArena)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Dnnl(_nativePtr, useArena));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Dnnl(handle, useArena));
}
///
@@ -108,7 +108,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_CUDA(int deviceId)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_CUDA(_nativePtr, deviceId));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_CUDA(handle, deviceId));
}
///
@@ -116,7 +116,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_NGraph(string nGraphBackendType)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_NGraph(_nativePtr, nGraphBackendType));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_NGraph(handle, nGraphBackendType));
}
///
@@ -124,7 +124,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_OpenVINO(string deviceId = "")
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_OpenVINO(_nativePtr, deviceId));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_OpenVINO(handle, deviceId));
}
///
@@ -132,7 +132,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_Tensorrt(int deviceId)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Tensorrt(_nativePtr, deviceId));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Tensorrt(handle, deviceId));
}
///
@@ -140,7 +140,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_MIGraphX(int deviceId)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_MIGraphX(_nativePtr, deviceId));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_MIGraphX(handle, deviceId));
}
///
@@ -148,7 +148,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_Nnapi()
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Nnapi(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Nnapi(handle));
}
///
@@ -156,7 +156,7 @@ namespace Microsoft.ML.OnnxRuntime
///
public void AppendExecutionProvider_Nuphar(string settings = "")
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Nuphar(_nativePtr, 1, settings));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsAppendExecutionProvider_Nuphar(handle, 1, settings));
}
#endregion //ExecutionProviderAppends
@@ -164,7 +164,7 @@ namespace Microsoft.ML.OnnxRuntime
public void RegisterCustomOpLibrary(string libraryPath)
{
IntPtr libraryHandle = IntPtr.Zero;
- NativeApiStatus.VerifySuccess(NativeMethods.OrtRegisterCustomOpsLibrary(_nativePtr, libraryPath, out libraryHandle));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtRegisterCustomOpsLibrary(handle, libraryPath, out libraryHandle));
}
#endregion
@@ -173,11 +173,13 @@ namespace Microsoft.ML.OnnxRuntime
{
get
{
- return _nativePtr;
+ return handle;
}
}
-
#region Public Properties
+
+ public override bool IsInvalid { get { return handle == IntPtr.Zero; } }
+
///
/// Enables the use of the memory allocation patterns in the first Run() call for subsequent runs. Default = true.
///
@@ -191,19 +193,18 @@ namespace Microsoft.ML.OnnxRuntime
{
if (!_enableMemoryPattern && value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtEnableMemPattern(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtEnableMemPattern(handle));
_enableMemoryPattern = true;
}
else if (_enableMemoryPattern && !value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtDisableMemPattern(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtDisableMemPattern(handle));
_enableMemoryPattern = false;
}
}
}
private bool _enableMemoryPattern = true;
-
///
/// Path prefix to use for output of profiling data
///
@@ -227,12 +228,12 @@ namespace Microsoft.ML.OnnxRuntime
{
if (!_enableProfiling && value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtEnableProfiling(_nativePtr, NativeMethods.GetPlatformSerializedString(ProfileOutputPathPrefix)));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtEnableProfiling(handle, NativeMethods.GetPlatformSerializedString(ProfileOutputPathPrefix)));
_enableProfiling = true;
}
else if (_enableProfiling && !value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtDisableProfiling(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtDisableProfiling(handle));
_enableProfiling = false;
}
}
@@ -252,7 +253,7 @@ namespace Microsoft.ML.OnnxRuntime
{
if (value != _optimizedModelFilePath)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetOptimizedModelFilePath(_nativePtr, NativeMethods.GetPlatformSerializedString(value)));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetOptimizedModelFilePath(handle, NativeMethods.GetPlatformSerializedString(value)));
_optimizedModelFilePath = value;
}
}
@@ -274,12 +275,12 @@ namespace Microsoft.ML.OnnxRuntime
{
if (!_enableCpuMemArena && value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtEnableCpuMemArena(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtEnableCpuMemArena(handle));
_enableCpuMemArena = true;
}
else if (_enableCpuMemArena && !value)
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtDisableCpuMemArena(_nativePtr));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtDisableCpuMemArena(handle));
_enableCpuMemArena = false;
}
}
@@ -300,7 +301,7 @@ namespace Microsoft.ML.OnnxRuntime
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionLogId(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionLogId(handle, value));
_logId = value;
}
}
@@ -317,7 +318,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionLogSeverityLevel(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionLogSeverityLevel(handle, value));
_logSeverityLevel = value;
}
}
@@ -335,7 +336,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionLogVerbosityLevel(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionLogVerbosityLevel(handle, value));
_logVerbosityLevel = value;
}
}
@@ -354,7 +355,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetIntraOpNumThreads(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetIntraOpNumThreads(handle, value));
_intraOpNumThreads = value;
}
}
@@ -373,7 +374,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetInterOpNumThreads(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetInterOpNumThreads(handle, value));
_interOpNumThreads = value;
}
}
@@ -390,7 +391,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionGraphOptimizationLevel(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionGraphOptimizationLevel(handle, value));
_graphOptimizationLevel = value;
}
}
@@ -408,7 +409,7 @@ namespace Microsoft.ML.OnnxRuntime
}
set
{
- NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionExecutionMode(_nativePtr, value));
+ NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionExecutionMode(handle, value));
_executionMode = value;
}
}
@@ -448,21 +449,13 @@ namespace Microsoft.ML.OnnxRuntime
#endregion
- #region IDisposable
+ #region SafeHandle
- public void Dispose()
+ protected override bool ReleaseHandle()
{
- GC.SuppressFinalize(this);
- Dispose(true);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- NativeMethods.OrtReleaseSessionOptions(_nativePtr);
- _nativePtr = IntPtr.Zero;
- }
+ NativeMethods.OrtReleaseSessionOptions(handle);
+ handle = IntPtr.Zero;
+ return true;
}
#endregion