Fixed ProtoWriter Dispose

this broke protobuf
This commit is contained in:
MaxXor 2015-03-17 22:28:03 +01:00
parent b45ebd33ae
commit 84b7fc901e
2 changed files with 50 additions and 123 deletions

View File

@ -474,60 +474,22 @@ public ProtoWriter(Stream dest, TypeModel model, SerializationContext context)
/// </summary>
void IDisposable.Dispose()
{
// Dispose of it all.
Dispose(true);
// Don't waste time finalizing because we have already disposed of the object ourselves.
GC.SuppressFinalize(this);
}
/// <summary>
/// Release some resources of the ProtoWriter, but NOT the underlying stream.
/// </summary>
public void Dispose()
{
// ProtoWriter's own definition of dispose. Will release some resources, but not the underlying stream.
Dispose(false);
Dispose();
}
/// <summary>
/// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream.
/// </summary>
/// <param name="disposing">Determines whether to dispose of everything, including the underlying stream.</param>
public void Dispose(bool disposing)
public void Dispose()
{
if (!disposed)
if (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;
}
Flush(this);
dest.Dispose();
dest = null;
}
}
~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);
model = null;
BufferPool.ReleaseBufferToPool(ref ioBuffer);
}
private byte[] ioBuffer;

View File

@ -24,7 +24,7 @@ public sealed class ProtoWriter : IDisposable
private Stream dest;
TypeModel model;
private bool disposed = false;
/// <summary>
/// Write an encapsulated sub-object, using the supplied unique key (reprasenting a type).
/// </summary>
@ -56,7 +56,7 @@ public static void WriteObject(object value, int key, ProtoWriter writer)
TypeModel.ThrowUnexpectedType(value.GetType());
}
EndSubItem(token, writer);
#endif
#endif
}
/// <summary>
/// Write an encapsulated sub-object, using the supplied unique key (reprasenting a type) - but the
@ -116,18 +116,18 @@ internal static void WriteObject(object value, int key, ProtoWriter writer, Pref
writer.model.Serialize(key, value, writer);
}
EndSubItem(token, writer, style);
#endif
#endif
}
internal int GetTypeKey(ref Type type)
{
return model.GetKey(ref type);
}
private readonly NetObjectCache netCache = new NetObjectCache();
internal NetObjectCache NetCache
{
get { return netCache;}
get { return netCache; }
}
private int fieldNumber, flushLock;
@ -136,11 +136,12 @@ internal NetObjectCache NetCache
/// <summary>
/// Writes a field-header, indicating the format of the next data we plan to write.
/// </summary>
public static void WriteFieldHeader(int fieldNumber, WireType wireType, ProtoWriter writer) {
public static void WriteFieldHeader(int fieldNumber, WireType wireType, ProtoWriter writer)
{
if (writer == null) throw new ArgumentNullException("writer");
if (writer.wireType != WireType.None) throw new InvalidOperationException("Cannot write a " + wireType.ToString()
+ " header until the " + writer.wireType.ToString() + " data has been written");
if(fieldNumber < 0) throw new ArgumentOutOfRangeException("fieldNumber");
if (fieldNumber < 0) throw new ArgumentOutOfRangeException("fieldNumber");
#if DEBUG
switch (wireType)
{ // validate requested header-type
@ -154,10 +155,11 @@ internal NetObjectCache NetCache
case WireType.None:
case WireType.EndGroup:
default:
throw new ArgumentException("Invalid wire-type: " + wireType.ToString(), "wireType");
throw new ArgumentException("Invalid wire-type: " + wireType.ToString(), "wireType");
}
#endif
if (writer.packedFieldNumber == 0) {
if (writer.packedFieldNumber == 0)
{
writer.fieldNumber = fieldNumber;
writer.wireType = wireType;
WriteHeaderCore(fieldNumber, wireType, writer);
@ -226,7 +228,7 @@ public static void WriteBytes(byte[] data, int offset, int length, ProtoWriter w
// now just write directly to the underlying stream
writer.dest.Write(data, offset, length);
writer.position += length; // since we've flushed offset etc is 0, and remains
// zero since we're writing directly to the stream
// zero since we're writing directly to the stream
return;
}
throw CreateException(writer);
@ -239,13 +241,13 @@ private static void CopyRawFromStream(Stream source, ProtoWriter writer)
{
byte[] buffer = writer.ioBuffer;
int space = buffer.Length - writer.ioIndex, bytesRead = 1; // 1 here to spoof case where already full
// try filling the buffer first
while (space > 0 && (bytesRead = source.Read(buffer, writer.ioIndex, space)) > 0)
{
writer.ioIndex += bytesRead;
writer.position += bytesRead;
space -= bytesRead;
space -= bytesRead;
}
if (bytesRead <= 0) return; // all done using just the buffer; stream exhausted
@ -268,7 +270,7 @@ private static void CopyRawFromStream(Stream source, ProtoWriter writer)
// (128 is the minimum; there may actually be much
// more space than this in the buffer)
DemandSpace(128, writer);
if((bytesRead = source.Read(writer.ioBuffer, writer.ioIndex,
if ((bytesRead = source.Read(writer.ioBuffer, writer.ioIndex,
writer.ioBuffer.Length - writer.ioIndex)) <= 0) break;
writer.position += bytesRead;
writer.ioIndex += bytesRead;
@ -305,7 +307,7 @@ private void CheckRecursionStackAndPush(object instance)
{
#if DEBUG
Helpers.DebugWriteLine("Stack:");
foreach(object obj in recursionStack)
foreach (object obj in recursionStack)
{
Helpers.DebugWriteLine(obj == null ? "<null>" : obj.ToString());
}
@ -324,7 +326,7 @@ private static SubItemToken StartSubItem(object instance, ProtoWriter writer, bo
{
writer.CheckRecursionStackAndPush(instance);
}
if(writer.packedFieldNumber != 0) throw new InvalidOperationException("Cannot begin a sub-item while performing packed encoding");
if (writer.packedFieldNumber != 0) throw new InvalidOperationException("Cannot begin a sub-item while performing packed encoding");
switch (writer.wireType)
{
case WireType.StartGroup:
@ -332,7 +334,7 @@ private static SubItemToken StartSubItem(object instance, ProtoWriter writer, bo
return new SubItemToken(-writer.fieldNumber);
case WireType.String:
#if DEBUG
if(writer.model != null && writer.model.ForwardsOnly)
if (writer.model != null && writer.model.ForwardsOnly)
{
throw new ProtoException("Should not be buffering data");
}
@ -385,7 +387,7 @@ private static void EndSubItem(SubItemToken token, ProtoWriter writer, PrefixSty
// so we're backfilling the length into an existing sequence
int len;
switch(style)
switch (style)
{
case PrefixStyle.Fixed32:
len = (int)((writer.ioIndex - value) - 4);
@ -439,7 +441,7 @@ private static void EndSubItem(SubItemToken token, ProtoWriter writer, PrefixSty
{
ProtoWriter.Flush(writer);
}
}
/// <summary>
@ -460,7 +462,7 @@ public ProtoWriter(Stream dest, TypeModel model, SerializationContext context)
if (context == null) { context = SerializationContext.Default; }
else { context.Freeze(); }
this.context = context;
}
private readonly SerializationContext context;
@ -474,60 +476,22 @@ public ProtoWriter(Stream dest, TypeModel model, SerializationContext context)
/// </summary>
void IDisposable.Dispose()
{
// Dispose of it all.
Dispose(true);
// Don't waste time finalizing because we have already disposed of the object ourselves.
GC.SuppressFinalize(this);
}
/// <summary>
/// Release some resources of the ProtoWriter, but NOT the underlying stream.
/// </summary>
public void Dispose()
{
// ProtoWriter's own definition of dispose. Will release some resources, but not the underlying stream.
Dispose(false);
Dispose();
}
/// <summary>
/// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream.
/// </summary>
/// <param name="disposing">Determines whether to dispose of everything, including the underlying stream.</param>
public void Dispose(bool disposing)
public void Dispose()
{
if (!disposed)
if (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;
}
Flush(this);
dest.Dispose();
dest = null;
}
}
~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);
model = null;
BufferPool.ReleaseBufferToPool(ref ioBuffer);
}
private byte[] ioBuffer;
@ -580,7 +544,7 @@ internal static void Flush(ProtoWriter writer)
if (writer.flushLock == 0 && writer.ioIndex != 0)
{
writer.dest.Write(writer.ioBuffer, 0, writer.ioIndex);
writer.ioIndex = 0;
writer.ioIndex = 0;
}
}
@ -591,18 +555,19 @@ private static void WriteUInt32Variant(uint value, ProtoWriter writer)
{
DemandSpace(5, writer);
int count = 0;
do {
do
{
writer.ioBuffer[writer.ioIndex++] = (byte)((value & 0x7F) | 0x80);
count++;
} while ((value >>= 7) != 0);
writer.ioBuffer[writer.ioIndex - 1] &= 0x7F;
writer.position += count;
}
static readonly UTF8Encoding encoding = new UTF8Encoding();
internal static uint Zig(int value)
{
{
return (uint)((value << 1) ^ (value >> 31));
}
internal static ulong Zig(long value)
@ -806,7 +771,7 @@ public static void WriteInt32(int value, ProtoWriter writer)
{
case WireType.Fixed32:
DemandSpace(4, writer);
WriteInt32ToBuffer(value, writer.ioBuffer, writer.ioIndex);
WriteInt32ToBuffer(value, writer.ioBuffer, writer.ioIndex);
IncrementedAndReset(4, writer);
return;
case WireType.Fixed64:
@ -850,17 +815,17 @@ public static void WriteInt32(int value, ProtoWriter writer)
default:
throw CreateException(writer);
}
}
/// <summary>
/// Writes a double-precision number to the stream; supported wire-types: Fixed32, Fixed64
/// </summary>
public
#if !FEAT_SAFE
unsafe
unsafe
#endif
static void WriteDouble(double value, ProtoWriter writer)
static void WriteDouble(double value, ProtoWriter writer)
{
if (writer == null) throw new ArgumentNullException("writer");
switch (writer.wireType)
@ -888,11 +853,11 @@ static void WriteDouble(double value, ProtoWriter writer)
/// <summary>
/// Writes a single-precision number to the stream; supported wire-types: Fixed32, Fixed64
/// </summary>
public
public
#if !FEAT_SAFE
unsafe
unsafe
#endif
static void WriteSingle(float value, ProtoWriter writer)
static void WriteSingle(float value, ProtoWriter writer)
{
if (writer == null) throw new ArgumentNullException("writer");
switch (writer.wireType)
@ -944,7 +909,7 @@ public static void AppendExtensionData(IExtensible instance, ProtoWriter writer)
if (writer == null) throw new ArgumentNullException("writer");
// we expect the writer to be raw here; the extension data will have the
// header detail, so we'll copy it implicitly
if(writer.wireType != WireType.None) throw CreateException(writer);
if (writer.wireType != WireType.None) throw CreateException(writer);
IExtension extn = instance.GetExtensionObject(false);
if (extn != null)