private void DecompressChunk(object context) { DecompressChunkParms parms = (DecompressChunkParms)context; try { DecompressChunk(parms.CompressedBytes, parms.ChunkSize, parms.ChunkOffset, parms.DeferredFormatter); } catch (Exception ex) { parms.Exceptions.Add(ex); } }
void IDeferredSerializable.FinishDeserialization(Stream input, DeferredFormatter context) { // Allocate the memory if (this.bitmapWidth != 0 && this.bitmapHeight != 0) { this.voidStar = Allocate(this.bitmapWidth, this.bitmapHeight, out this.bitmapHandle).ToPointer(); this.valid = true; } else { this.voidStar = Allocate(this.length).ToPointer(); this.valid = true; } // formatVersion should equal 0 int formatVersion = input.ReadByte(); if (formatVersion == -1) { throw new EndOfStreamException(); } if (formatVersion != 0 && formatVersion != 1) { throw new SerializationException("formatVersion was neither zero nor one"); } // chunkSize uint chunkSize = ReadUInt(input); PaintDotNet.Threading.ThreadPool threadPool = new PaintDotNet.Threading.ThreadPool(Processor.LogicalCpuCount); ArrayList exceptions = new ArrayList(Processor.LogicalCpuCount); WaitCallback callback = new WaitCallback(DecompressChunk); // calculate chunkCount uint chunkCount = (uint)((this.length + (long)chunkSize - 1) / (long)chunkSize); bool[] chunksFound = new bool[chunkCount]; for (uint i = 0; i < chunkCount; ++i) { // chunkNumber uint chunkNumber = ReadUInt(input); if (chunkNumber >= chunkCount) { throw new SerializationException("chunkNumber read from stream is out of bounds"); } if (chunksFound[chunkNumber]) { throw new SerializationException("already encountered chunk #" + chunkNumber.ToString()); } chunksFound[chunkNumber] = true; // dataSize uint dataSize = ReadUInt(input); // calculate chunkOffset long chunkOffset = (long)chunkNumber * (long)chunkSize; // calculate decompressed chunkSize uint thisChunkSize = Math.Min(chunkSize, (uint)(this.length - chunkOffset)); // bounds checking if (chunkOffset < 0 || chunkOffset >= this.length || chunkOffset + thisChunkSize > this.length) { throw new SerializationException("data was specified to be out of bounds"); } // read compressed data byte[] compressedBytes = new byte[dataSize]; Utility.ReadFromStream(input, compressedBytes, 0, compressedBytes.Length); // decompress data if (formatVersion == 0) { DecompressChunkParms parms = new DecompressChunkParms(compressedBytes, thisChunkSize, chunkOffset, context, exceptions); threadPool.QueueUserWorkItem(callback, parms); } else { fixed(byte *pbSrc = compressedBytes) { Memory.Copy((void *)((byte *)this.VoidStar + chunkOffset), (void *)pbSrc, thisChunkSize); } } } threadPool.Drain(); if (exceptions.Count > 0) { throw new SerializationException("Exception thrown by worker thread", (Exception)exceptions[0]); } }
void IDeferredSerializable.FinishDeserialization(Stream input, DeferredFormatter context) { // Allocate the memory if (this.bitmapWidth != 0 && this.bitmapHeight != 0) { this.voidStar = Allocate(this.bitmapWidth, this.bitmapHeight, out this.bitmapHandle).ToPointer(); this.valid = true; } else { this.voidStar = Allocate(this.length).ToPointer(); this.valid = true; } // formatVersion should equal 0 int formatVersion = input.ReadByte(); if (formatVersion == -1) { throw new EndOfStreamException(); } if (formatVersion != 0 && formatVersion != 1) { throw new SerializationException("formatVersion was neither zero nor one"); } // chunkSize uint chunkSize = ReadUInt(input); PaintDotNet.Threading.ThreadPool threadPool = new PaintDotNet.Threading.ThreadPool(Processor.LogicalCpuCount); ArrayList exceptions = new ArrayList(Processor.LogicalCpuCount); WaitCallback callback = new WaitCallback(DecompressChunk); // calculate chunkCount uint chunkCount = (uint)((this.length + (long)chunkSize - 1) / (long)chunkSize); bool[] chunksFound = new bool[chunkCount]; for (uint i = 0; i < chunkCount; ++i) { // chunkNumber uint chunkNumber = ReadUInt(input); if (chunkNumber >= chunkCount) { throw new SerializationException("chunkNumber read from stream is out of bounds"); } if (chunksFound[chunkNumber]) { throw new SerializationException("already encountered chunk #" + chunkNumber.ToString()); } chunksFound[chunkNumber] = true; // dataSize uint dataSize = ReadUInt(input); // calculate chunkOffset long chunkOffset = (long)chunkNumber * (long)chunkSize; // calculate decompressed chunkSize uint thisChunkSize = Math.Min(chunkSize, (uint)(this.length - chunkOffset)); // bounds checking if (chunkOffset < 0 || chunkOffset >= this.length || chunkOffset + thisChunkSize > this.length) { throw new SerializationException("data was specified to be out of bounds"); } // read compressed data byte[] compressedBytes = new byte[dataSize]; Utility.ReadFromStream(input, compressedBytes, 0, compressedBytes.Length); // decompress data if (formatVersion == 0) { DecompressChunkParms parms = new DecompressChunkParms(compressedBytes, thisChunkSize, chunkOffset, context, exceptions); threadPool.QueueUserWorkItem(callback, parms); } else { fixed (byte *pbSrc = compressedBytes) { Memory.Copy((void *)((byte *)this.VoidStar + chunkOffset), (void *)pbSrc, thisChunkSize); } } } threadPool.Drain(); if (exceptions.Count > 0) { throw new SerializationException("Exception thrown by worker thread", (Exception)exceptions[0]); } }