From ba2f2a0b2a8b54813d7e84a20ce861bfee1bf8dc Mon Sep 17 00:00:00 2001 From: yankejustin Date: Tue, 17 Mar 2015 13:28:23 -0400 Subject: [PATCH] Correctly implemented IDisposable Correctly implemented IDisposable on the client's and server's ProtoWriter. --- Client/Core/ProtoBuf/ProtoWriter.cs | 31 +++++++++++--- Server/Core/ProtoBuf/ProtoWriter.cs | 64 +++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/Client/Core/ProtoBuf/ProtoWriter.cs b/Client/Core/ProtoBuf/ProtoWriter.cs index ad15fa82..013df802 100644 --- a/Client/Core/ProtoBuf/ProtoWriter.cs +++ b/Client/Core/ProtoBuf/ProtoWriter.cs @@ -471,18 +471,31 @@ public ProtoWriter(Stream dest, TypeModel model, SerializationContext context) /// public SerializationContext Context { get { return context; } } + /// + /// Disposes and cleans up all unused resources that is used by the object. + /// void IDisposable.Dispose() { - Dispose(false); - } - - void Dispose() - { + // Dispose of it all. Dispose(true); + // Don't waste time finalizing because we have already disposed of the object ourselves. GC.SuppressFinalize(this); } + /// + /// Release some resources of the ProtoWriter, but NOT the underlying stream. + /// + public void Dispose() + { + // ProtoWriter's own definition of dispose. Will release some resources, but not the underlying stream. + Dispose(false); + } + + /// + /// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream. + /// + /// Determines whether to dispose of everything, including the underlying stream. public void Dispose(bool disposing) { if (!disposed) @@ -512,6 +525,14 @@ public void Dispose(bool disposing) } } + ~ProtoWriter() + { + // The object has been destroyed. Make sure everything is cleaned up. + // If the object has already been fully disposed, this finalizer would + // be suppressed. + Dispose(true); + } + private byte[] ioBuffer; private int ioIndex; // note that this is used by some of the unit tests and should not be removed diff --git a/Server/Core/ProtoBuf/ProtoWriter.cs b/Server/Core/ProtoBuf/ProtoWriter.cs index c4100c00..5492b76b 100644 --- a/Server/Core/ProtoBuf/ProtoWriter.cs +++ b/Server/Core/ProtoBuf/ProtoWriter.cs @@ -23,6 +23,8 @@ public sealed class ProtoWriter : IDisposable { private Stream dest; TypeModel model; + private bool disposed = false; + /// /// Write an encapsulated sub-object, using the supplied unique key (reprasenting a type). /// @@ -467,20 +469,66 @@ public ProtoWriter(Stream dest, TypeModel model, SerializationContext context) /// Addition information about this serialization operation. /// public SerializationContext Context { get { return context; } } + + /// + /// Disposes and cleans up all unused resources that is used by the object. + /// void IDisposable.Dispose() { - Dispose(); + // Dispose of it all. + Dispose(true); + + // Don't waste time finalizing because we have already disposed of the object ourselves. + GC.SuppressFinalize(this); } - private void Dispose() + + /// + /// Release some resources of the ProtoWriter, but NOT the underlying stream. + /// + public void Dispose() { - if (dest != null) + // ProtoWriter's own definition of dispose. Will release some resources, but not the underlying stream. + Dispose(false); + } + + /// + /// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream. + /// + /// Determines whether to dispose of everything, including the underlying stream. + public void Dispose(bool disposing) + { + if (!disposed) { - Flush(this); - dest.Dispose(); - dest = null; + model = null; + BufferPool.ReleaseBufferToPool(ref ioBuffer); + + if (disposing) + { + if (dest != null) + { + try + { + // Flush can throw a few exceptions, so make sure that, even if it messes up, dispose of the underlying stream. + Flush(this); + } + finally + { + dest.Dispose(); + dest = null; + } + } + + disposed = true; + } } - model = null; - BufferPool.ReleaseBufferToPool(ref ioBuffer); + } + + ~ProtoWriter() + { + // The object has been destroyed. Make sure everything is cleaned up. + // If the object has already been fully disposed, this finalizer would + // be suppressed. + Dispose(true); } private byte[] ioBuffer;