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> /// </summary>
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
// Dispose of it all. Dispose();
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);
} }
/// <summary> /// <summary>
/// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream. /// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream.
/// </summary> /// </summary>
/// <param name="disposing">Determines whether to dispose of everything, including the underlying stream.</param> public void Dispose()
public void Dispose(bool disposing)
{ {
if (!disposed) if (dest != null)
{ {
model = null; Flush(this);
BufferPool.ReleaseBufferToPool(ref ioBuffer); dest.Dispose();
dest = null;
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; private byte[] ioBuffer;

View File

@ -127,7 +127,7 @@ internal int GetTypeKey(ref Type type)
private readonly NetObjectCache netCache = new NetObjectCache(); private readonly NetObjectCache netCache = new NetObjectCache();
internal NetObjectCache NetCache internal NetObjectCache NetCache
{ {
get { return netCache;} get { return netCache; }
} }
private int fieldNumber, flushLock; private int fieldNumber, flushLock;
@ -136,11 +136,12 @@ internal NetObjectCache NetCache
/// <summary> /// <summary>
/// Writes a field-header, indicating the format of the next data we plan to write. /// Writes a field-header, indicating the format of the next data we plan to write.
/// </summary> /// </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 == null) throw new ArgumentNullException("writer");
if (writer.wireType != WireType.None) throw new InvalidOperationException("Cannot write a " + wireType.ToString() if (writer.wireType != WireType.None) throw new InvalidOperationException("Cannot write a " + wireType.ToString()
+ " header until the " + writer.wireType.ToString() + " data has been written"); + " 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 #if DEBUG
switch (wireType) switch (wireType)
{ // validate requested header-type { // validate requested header-type
@ -157,7 +158,8 @@ internal NetObjectCache NetCache
throw new ArgumentException("Invalid wire-type: " + wireType.ToString(), "wireType"); throw new ArgumentException("Invalid wire-type: " + wireType.ToString(), "wireType");
} }
#endif #endif
if (writer.packedFieldNumber == 0) { if (writer.packedFieldNumber == 0)
{
writer.fieldNumber = fieldNumber; writer.fieldNumber = fieldNumber;
writer.wireType = wireType; writer.wireType = wireType;
WriteHeaderCore(fieldNumber, wireType, writer); 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 // now just write directly to the underlying stream
writer.dest.Write(data, offset, length); writer.dest.Write(data, offset, length);
writer.position += length; // since we've flushed offset etc is 0, and remains 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; return;
} }
throw CreateException(writer); throw CreateException(writer);
@ -268,7 +270,7 @@ private static void CopyRawFromStream(Stream source, ProtoWriter writer)
// (128 is the minimum; there may actually be much // (128 is the minimum; there may actually be much
// more space than this in the buffer) // more space than this in the buffer)
DemandSpace(128, writer); 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.ioBuffer.Length - writer.ioIndex)) <= 0) break;
writer.position += bytesRead; writer.position += bytesRead;
writer.ioIndex += bytesRead; writer.ioIndex += bytesRead;
@ -305,7 +307,7 @@ private void CheckRecursionStackAndPush(object instance)
{ {
#if DEBUG #if DEBUG
Helpers.DebugWriteLine("Stack:"); Helpers.DebugWriteLine("Stack:");
foreach(object obj in recursionStack) foreach (object obj in recursionStack)
{ {
Helpers.DebugWriteLine(obj == null ? "<null>" : obj.ToString()); Helpers.DebugWriteLine(obj == null ? "<null>" : obj.ToString());
} }
@ -324,7 +326,7 @@ private static SubItemToken StartSubItem(object instance, ProtoWriter writer, bo
{ {
writer.CheckRecursionStackAndPush(instance); 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) switch (writer.wireType)
{ {
case WireType.StartGroup: case WireType.StartGroup:
@ -332,7 +334,7 @@ private static SubItemToken StartSubItem(object instance, ProtoWriter writer, bo
return new SubItemToken(-writer.fieldNumber); return new SubItemToken(-writer.fieldNumber);
case WireType.String: case WireType.String:
#if DEBUG #if DEBUG
if(writer.model != null && writer.model.ForwardsOnly) if (writer.model != null && writer.model.ForwardsOnly)
{ {
throw new ProtoException("Should not be buffering data"); 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 // so we're backfilling the length into an existing sequence
int len; int len;
switch(style) switch (style)
{ {
case PrefixStyle.Fixed32: case PrefixStyle.Fixed32:
len = (int)((writer.ioIndex - value) - 4); len = (int)((writer.ioIndex - value) - 4);
@ -474,60 +476,22 @@ public ProtoWriter(Stream dest, TypeModel model, SerializationContext context)
/// </summary> /// </summary>
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
// Dispose of it all. Dispose();
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);
} }
/// <summary> /// <summary>
/// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream. /// Releases some resources of the ProtoWriter. Optionally dispose of it all, including the underlying stream.
/// </summary> /// </summary>
/// <param name="disposing">Determines whether to dispose of everything, including the underlying stream.</param> public void Dispose()
public void Dispose(bool disposing)
{ {
if (!disposed) if (dest != null)
{ {
model = null; Flush(this);
BufferPool.ReleaseBufferToPool(ref ioBuffer); dest.Dispose();
dest = null;
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; private byte[] ioBuffer;
@ -591,7 +555,8 @@ private static void WriteUInt32Variant(uint value, ProtoWriter writer)
{ {
DemandSpace(5, writer); DemandSpace(5, writer);
int count = 0; int count = 0;
do { do
{
writer.ioBuffer[writer.ioIndex++] = (byte)((value & 0x7F) | 0x80); writer.ioBuffer[writer.ioIndex++] = (byte)((value & 0x7F) | 0x80);
count++; count++;
} while ((value >>= 7) != 0); } while ((value >>= 7) != 0);
@ -857,10 +822,10 @@ public static void WriteInt32(int value, ProtoWriter writer)
/// </summary> /// </summary>
public public
#if !FEAT_SAFE #if !FEAT_SAFE
unsafe unsafe
#endif #endif
static void WriteDouble(double value, ProtoWriter writer) static void WriteDouble(double value, ProtoWriter writer)
{ {
if (writer == null) throw new ArgumentNullException("writer"); if (writer == null) throw new ArgumentNullException("writer");
switch (writer.wireType) switch (writer.wireType)
@ -890,9 +855,9 @@ static void WriteDouble(double value, ProtoWriter writer)
/// </summary> /// </summary>
public public
#if !FEAT_SAFE #if !FEAT_SAFE
unsafe unsafe
#endif #endif
static void WriteSingle(float value, ProtoWriter writer) static void WriteSingle(float value, ProtoWriter writer)
{ {
if (writer == null) throw new ArgumentNullException("writer"); if (writer == null) throw new ArgumentNullException("writer");
switch (writer.wireType) switch (writer.wireType)
@ -944,7 +909,7 @@ public static void AppendExtensionData(IExtensible instance, ProtoWriter writer)
if (writer == null) throw new ArgumentNullException("writer"); if (writer == null) throw new ArgumentNullException("writer");
// we expect the writer to be raw here; the extension data will have the // we expect the writer to be raw here; the extension data will have the
// header detail, so we'll copy it implicitly // 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); IExtension extn = instance.GetExtensionObject(false);
if (extn != null) if (extn != null)