Use simple IDisposable pattern.

This commit is contained in:
Stephen Kennedy 2019-11-05 15:42:38 +00:00
Родитель 907f034535
Коммит fa879ca991
3 изменённых файлов: 35 добавлений и 121 удалений

Просмотреть файл

@ -1,101 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using System;
using System.Threading;
namespace Microsoft.MixedReality.Sharing.Utilities
{
/// <summary>
/// This is a base class for common IDisposable implementation.
/// </summary>
/// <remarks>Follows https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose </remarks>
public class DisposableBase : IDisposable
{
private string objectName;
private ThreadLocal<bool> insideDisposeFunction = new ThreadLocal<bool>(() => false);
/// <summary>
/// Is the current object disposed.
/// </summary>
public bool IsDisposed { get; private set; }
/// <summary>
/// The name of the current object.
/// </summary>
protected virtual string ObjectName => objectName ?? (objectName = GetType().Name);
~DisposableBase()
{
Dispose(false);
}
/// <summary>
/// Dispose the current object.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool isDisposing)
{
if (IsDisposed)
{
return;
}
IsDisposed = true;
// If the finalizer is running, don't access the insideDisposeFunction, as it will
// also be finalizing.
if (isDisposing)
{
insideDisposeFunction = null;
}
else
{
insideDisposeFunction.Value = true;
}
try
{
if (isDisposing)
{
OnManagedDispose();
}
OnUnmanagedDispose();
}
finally
{
if (insideDisposeFunction != null)
{
insideDisposeFunction.Value = false;
}
}
}
/// <summary>
/// Override this method to dispose of managed objects.
/// </summary>
protected virtual void OnManagedDispose() { }
/// <summary>
/// Override this method to dispose of unmanaged objects.
/// </summary>
protected virtual void OnUnmanagedDispose() { }
/// <summary>
/// A helper method to throw if the current object is disposed.
/// </summary>
protected void ThrowIfDisposed()
{
if (insideDisposeFunction == null || (!insideDisposeFunction.Value && IsDisposed))
{
throw new ObjectDisposedException(ObjectName);
}
}
}
}

Просмотреть файл

@ -876,13 +876,14 @@ namespace Microsoft.MixedReality.Sharing.Matchmaking
/// <summary>
/// Simple discovery agent for local networks.
/// </summary>
public class PeerDiscoveryAgent : DisposableBase, IDiscoveryAgent
public class PeerDiscoveryAgent : IDiscoveryAgent
{
/// The transport for this agent.
private readonly IPeerDiscoveryTransport transport_;
private Server server_;
private Client client_;
private Options options_;
private int disposed_ = 0;
// Counts how many things (local resources or discovery tasks) are using the transport.
private int transportRefCount_ = 0;
@ -950,19 +951,22 @@ namespace Microsoft.MixedReality.Sharing.Matchmaking
}
}
protected override void OnUnmanagedDispose()
public void Dispose()
{
server_?.Stop();
client_?.Stop();
// Give some time for the ByeBye message to be sent before shutting down the sockets.
// todo is there a smarter way to do this?
Task.Delay(1).Wait();
// Stop the network and prevent later disposals from trying to stop it again.
if (Interlocked.Exchange(ref transportRefCount_, 0) > 0)
if( Interlocked.CompareExchange(ref disposed_, 1, 0) == 0 )
{
transport_.Stop();
server_?.Stop();
client_?.Stop();
// Give some time for the ByeBye message to be sent before shutting down the sockets.
// todo is there a smarter way to do this?
Task.Delay(1).Wait();
// Stop the network and prevent later disposals from trying to stop it again.
if (Interlocked.Exchange(ref transportRefCount_, 0) > 0)
{
transport_.Stop();
}
}
}
}

Просмотреть файл

@ -16,7 +16,7 @@ namespace Microsoft.MixedReality.SpatialAlignment
/// Helper base class for <see cref="ISpatialCoordinateService"/> implementations.
/// </summary>
/// <typeparam name="TKey">They key for the <see cref="ISpatialCoordinate"/>.</typeparam>
public abstract class SpatialCoordinateServiceBase<TKey> : DisposableBase, ISpatialCoordinateService
public abstract class SpatialCoordinateServiceBase<TKey> : ISpatialCoordinateService
{
/// <inheritdoc />
public event Action<ISpatialCoordinate> CoordinatedDiscovered;
@ -29,9 +29,19 @@ namespace Microsoft.MixedReality.SpatialAlignment
private volatile bool isDiscovering = false;
private volatile int discoveryOrCreateRequests = 0;
private int isDisposed = 0;
protected readonly ConcurrentDictionary<TKey, ISpatialCoordinate> knownCoordinates = new ConcurrentDictionary<TKey, ISpatialCoordinate>();
protected void ThrowIfDisposed()
{
if (isDisposed != 0)
{
throw new ObjectDisposedException("SpatialCoordinateServiceBase");
}
}
/// <inheritdoc />
public bool IsTracking
{
@ -55,15 +65,16 @@ namespace Microsoft.MixedReality.SpatialAlignment
}
}
protected override void OnManagedDispose()
public void Dispose()
{
base.OnManagedDispose();
if (Interlocked.CompareExchange(ref isDisposed, 1, 0) == 0)
{
// Notify of dispose to any existing operations
disposedCTS.Cancel();
disposedCTS.Dispose();
// Notify of dispose to any existing operations
disposedCTS.Cancel();
disposedCTS.Dispose();
knownCoordinates.Clear();
knownCoordinates.Clear();
}
}
bool ISpatialCoordinateService.TryGetKnownCoordinate(string id, out ISpatialCoordinate spatialCoordinate)