Skip to content

Commit

Permalink
Reset a Base.Object deleter handle to an invalid handle upon Dispose(…
Browse files Browse the repository at this point in the history
…) so a disposed object can't continue to be used if the native handle is still alive. Add a new RefCountedDeleterHandle to differentiate between a non-refcounted DeleterHandle.
  • Loading branch information
JBBee committed Dec 26, 2019
1 parent 7296e4f commit 524740a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 27 deletions.
1 change: 1 addition & 0 deletions wrappers/csharp/Intel.RealSense/Base/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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"
)
30 changes: 6 additions & 24 deletions wrappers/csharp/Intel.RealSense/Base/DeleterHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ namespace Intel.RealSense.Base
/// </summary>
// 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;

Expand All @@ -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)
Expand Down
9 changes: 6 additions & 3 deletions wrappers/csharp/Intel.RealSense/Base/Object.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// Initializes a new instance of the <see cref="Object"/> class.
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
56 changes: 56 additions & 0 deletions wrappers/csharp/Intel.RealSense/Base/RefCountedDeleterHandle.cs
Original file line number Diff line number Diff line change
@@ -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;


/// <summary>
/// Native handle with deleter delegate to release unmanaged resources
/// The unmanaged resource is released when the refcount reaches 0
/// </summary>
// 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);
}
}
}

0 comments on commit 524740a

Please sign in to comment.