diff --git a/wrappers/csharp/Intel.RealSense/Base/CMakeLists.txt b/wrappers/csharp/Intel.RealSense/Base/CMakeLists.txt index 23883ab616..b850c1c328 100644 --- a/wrappers/csharp/Intel.RealSense/Base/CMakeLists.txt +++ b/wrappers/csharp/Intel.RealSense/Base/CMakeLists.txt @@ -1,6 +1,7 @@ target_sources(${LRS_DOTNET_TARGET} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/DeleterHandle.cs" + "${CMAKE_CURRENT_LIST_DIR}/RefCountedDeleterHandle.cs" "${CMAKE_CURRENT_LIST_DIR}/Object.cs" "${CMAKE_CURRENT_LIST_DIR}/PooledObject.cs" ) diff --git a/wrappers/csharp/Intel.RealSense/Base/DeleterHandle.cs b/wrappers/csharp/Intel.RealSense/Base/DeleterHandle.cs index d9e7f81c1a..6004b144c3 100644 --- a/wrappers/csharp/Intel.RealSense/Base/DeleterHandle.cs +++ b/wrappers/csharp/Intel.RealSense/Base/DeleterHandle.cs @@ -17,11 +17,10 @@ namespace Intel.RealSense.Base /// // TODO: CriticalFinalizerObject & CER //[DebuggerDisplay("{deleter?.Method.Name,nq}", Name = nameof(Deleter))] - internal sealed class DeleterHandle : IDisposable + internal class DeleterHandle : IDisposable { private IntPtr handle; private Deleter deleter; - private int refCount; public IntPtr Handle => handle; @@ -42,38 +41,21 @@ public void SetHandleAsInvalid() GC.SuppressFinalize(this); } - public void Retain() - { - refCount++; - } - public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } - public void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { if (handle == IntPtr.Zero) { return; - } - - if (refCount > 0) - { - refCount--; - if (refCount == 0) - { - deleter?.Invoke(handle); - handle = IntPtr.Zero; - } - } - else - { - deleter?.Invoke(handle); - handle = IntPtr.Zero; - } + } + + deleter?.Invoke(handle); + handle = IntPtr.Zero; } internal void Reset(IntPtr ptr) diff --git a/wrappers/csharp/Intel.RealSense/Base/Object.cs b/wrappers/csharp/Intel.RealSense/Base/Object.cs index 71455aec0a..0cae31eba5 100644 --- a/wrappers/csharp/Intel.RealSense/Base/Object.cs +++ b/wrappers/csharp/Intel.RealSense/Base/Object.cs @@ -13,7 +13,7 @@ public abstract class Object : IDisposable { // TODO: rename, kept for backwards compatiblity [DebuggerBrowsable(DebuggerBrowsableState.Never)] - internal DeleterHandle m_instance; + internal RefCountedDeleterHandle m_instance; /// /// Initializes a new instance of the class. @@ -28,7 +28,7 @@ protected Object(IntPtr ptr, Deleter deleter) throw new ArgumentNullException(nameof(ptr)); } - m_instance = new DeleterHandle(ptr, deleter); + m_instance = new RefCountedDeleterHandle(ptr, deleter); } protected Object(Object other) @@ -67,7 +67,10 @@ public void Dispose() protected virtual void Dispose(bool disposing) { - m_instance.Dispose(); + m_instance.Dispose(); + + //Reset the instance ref to an invalid handle + m_instance = new RefCountedDeleterHandle(); } internal void Reset(IntPtr ptr, Deleter deleter) diff --git a/wrappers/csharp/Intel.RealSense/Base/RefCountedDeleterHandle.cs b/wrappers/csharp/Intel.RealSense/Base/RefCountedDeleterHandle.cs new file mode 100644 index 0000000000..4ac29a1c55 --- /dev/null +++ b/wrappers/csharp/Intel.RealSense/Base/RefCountedDeleterHandle.cs @@ -0,0 +1,56 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2017 Intel Corporation. All Rights Reserved. + +namespace Intel.RealSense.Base +{ + using System; + using System.Diagnostics; + using System.Runtime.InteropServices; + using System.Security; + + + /// + /// Native handle with deleter delegate to release unmanaged resources + /// The unmanaged resource is released when the refcount reaches 0 + /// + // TODO: CriticalFinalizerObject & CER + //[DebuggerDisplay("{deleter?.Method.Name,nq}", Name = nameof(Deleter))] + internal class RefCountedDeleterHandle : DeleterHandle + { + private int refCount; + + public RefCountedDeleterHandle(IntPtr ptr, Deleter deleter) : base(ptr, deleter) + { + Retain(); + } + + public RefCountedDeleterHandle() : base(IntPtr.Zero, null) + { + SetHandleAsInvalid(); + } + + public void Retain() + { + refCount++; + } + + protected override void Dispose(bool disposing) + { + if (Handle == IntPtr.Zero) + { + return; + } + + refCount--; + if (refCount == 0) + { + base.Dispose(disposing); + } + } + + ~RefCountedDeleterHandle() + { + Dispose(false); + } + } +} \ No newline at end of file