private void _PerpetualWriterMethod(object state) { TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod START"); try { do { // wait for the next session TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(begin) PWM"); _sessionReset.WaitOne(); TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(done) PWM"); if (_isDisposed) { break; } TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.Reset() PWM"); _sessionReset.Reset(); // repeatedly write buffers as they become ready WorkItem workitem = null; Ionic.Zlib.CRC32 c = new Ionic.Zlib.CRC32(); do { workitem = _pool[_nextToWrite % _pc]; lock (workitem) { if (_noMoreInputForThisSegment) { TraceOutput(TraceBits.Write, "Write drain wi({0}) stat({1}) canuse({2}) cba({3})", workitem.index, workitem.status, (workitem.status == (int)WorkItem.Status.Compressed), workitem.compressedBytesAvailable); } do { if (workitem.status == (int)WorkItem.Status.Compressed) { TraceOutput(TraceBits.WriteBegin, "Write begin wi({0}) stat({1}) cba({2})", workitem.index, workitem.status, workitem.compressedBytesAvailable); workitem.status = (int)WorkItem.Status.Writing; _outStream.Write(workitem.compressed, 0, workitem.compressedBytesAvailable); c.Combine(workitem.crc, workitem.inputBytesAvailable); _totalBytesProcessed += workitem.inputBytesAvailable; _nextToWrite++; workitem.inputBytesAvailable = 0; workitem.status = (int)WorkItem.Status.Done; TraceOutput(TraceBits.WriteDone, "Write done wi({0}) stat({1}) cba({2})", workitem.index, workitem.status, workitem.compressedBytesAvailable); Monitor.Pulse(workitem); break; } else { int wcycles = 0; // I've locked a workitem I cannot use. // Therefore, wake someone else up, and then release the lock. while (workitem.status != (int)WorkItem.Status.Compressed) { TraceOutput(TraceBits.WriteWait, "Write waiting wi({0}) stat({1}) nw({2}) nf({3}) nomore({4})", workitem.index, workitem.status, _nextToWrite, _nextToFill, _noMoreInputForThisSegment); if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } wcycles++; // wake up someone else Monitor.Pulse(workitem); // release and wait Monitor.Wait(workitem); if (workitem.status == (int)WorkItem.Status.Compressed) { TraceOutput(TraceBits.WriteWait, "Write A-OK wi({0}) stat({1}) iba({2}) cba({3}) cyc({4})", workitem.index, workitem.status, workitem.inputBytesAvailable, workitem.compressedBytesAvailable, wcycles); } } if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } } }while (true); } if (_noMoreInputForThisSegment) { TraceOutput(TraceBits.Write, "Write nomore nw({0}) nf({1}) break({2})", _nextToWrite, _nextToFill, (_nextToWrite == _nextToFill)); } if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } } while (true); // Finish: // After writing a series of buffers, closing each one with // Flush.Sync, we now write the final one as Flush.Finish, and // then stop. byte[] buffer = new byte[128]; ZlibCodec compressor = new ZlibCodec(); int rc = compressor.InitializeDeflate(_compressLevel, false); compressor.InputBuffer = null; compressor.NextIn = 0; compressor.AvailableBytesIn = 0; compressor.OutputBuffer = buffer; compressor.NextOut = 0; compressor.AvailableBytesOut = buffer.Length; rc = compressor.Deflate(FlushType.Finish); if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) { throw new Exception("deflating: " + compressor.Message); } if (buffer.Length - compressor.AvailableBytesOut > 0) { TraceOutput(TraceBits.WriteBegin, "Write begin flush bytes({0})", buffer.Length - compressor.AvailableBytesOut); _outStream.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut); TraceOutput(TraceBits.WriteBegin, "Write done flush"); } compressor.EndDeflate(); _Crc32 = c.Crc32Result; // signal that writing is complete: TraceOutput(TraceBits.Synch, "Synch _writingDone.Set() PWM"); _writingDone.Set(); }while (true); } catch (System.Exception exc1) { lock (_eLock) { // expose the exception to the main thread if (_pendingException != null) { _pendingException = exc1; } } } TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod FINIS"); }
private void EmitPendingBuffers(bool doAll, bool mustWait) { if (!emitting) { emitting = true; if (doAll || mustWait) { _newlyCompressedBlob.WaitOne(); } do { int num = -1; int num2 = doAll ? 200 : (mustWait ? (-1) : 0); int num3 = -1; do { if (Monitor.TryEnter(_toWrite, num2)) { num3 = -1; try { if (_toWrite.Count > 0) { num3 = _toWrite.Dequeue(); } } finally { Monitor.Exit(_toWrite); } if (num3 >= 0) { WorkItem workItem = _pool[num3]; if (workItem.ordinal != _lastWritten + 1) { lock (_toWrite) { _toWrite.Enqueue(num3); } if (num == num3) { _newlyCompressedBlob.WaitOne(); num = -1; } else if (num == -1) { num = num3; } } else { num = -1; _outStream.Write(workItem.compressed, 0, workItem.compressedBytesAvailable); _runningCrc.Combine(workItem.crc, workItem.inputBytesAvailable); _totalBytesProcessed += workItem.inputBytesAvailable; workItem.inputBytesAvailable = 0; _lastWritten = workItem.ordinal; _toFill.Enqueue(workItem.index); if (num2 == -1) { num2 = 0; } } } } else { num3 = -1; } }while (num3 >= 0); }while (doAll && _lastWritten != _latestCompressed); emitting = false; } }
private void _PerpetualWriterMethod(object state) { TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod START"); try { do { // wait for the next session TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(begin) PWM"); _sessionReset.WaitOne(); TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(done) PWM"); if (_isDisposed) break; TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.Reset() PWM"); _sessionReset.Reset(); // repeatedly write buffers as they become ready WorkItem workitem = null; CRC32 c= new CRC32(); do { workitem = _pool[_nextToWrite % _pc]; lock(workitem) { if (_noMoreInputForThisSegment) TraceOutput(TraceBits.Write, "Write drain wi({0}) stat({1}) canuse({2}) cba({3})", workitem.index, workitem.status, (workitem.status == (int)WorkItem.Status.Compressed), workitem.compressedBytesAvailable); do { if (workitem.status == (int)WorkItem.Status.Compressed) { TraceOutput(TraceBits.WriteBegin, "Write begin wi({0}) stat({1}) cba({2})", workitem.index, workitem.status, workitem.compressedBytesAvailable); workitem.status = (int)WorkItem.Status.Writing; _outStream.Write(workitem.compressed, 0, workitem.compressedBytesAvailable); c.Combine(workitem.crc, workitem.inputBytesAvailable); _totalBytesProcessed += workitem.inputBytesAvailable; _nextToWrite++; workitem.inputBytesAvailable= 0; workitem.status = (int)WorkItem.Status.Done; TraceOutput(TraceBits.WriteDone, "Write done wi({0}) stat({1}) cba({2})", workitem.index, workitem.status, workitem.compressedBytesAvailable); Monitor.Pulse(workitem); break; } else { int wcycles = 0; // I've locked a workitem I cannot use. // Therefore, wake someone else up, and then release the lock. while (workitem.status != (int)WorkItem.Status.Compressed) { TraceOutput(TraceBits.WriteWait, "Write waiting wi({0}) stat({1}) nw({2}) nf({3}) nomore({4})", workitem.index, workitem.status, _nextToWrite, _nextToFill, _noMoreInputForThisSegment ); if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) break; wcycles++; // wake up someone else Monitor.Pulse(workitem); // release and wait Monitor.Wait(workitem); if (workitem.status == (int)WorkItem.Status.Compressed) TraceOutput(TraceBits.WriteWait, "Write A-OK wi({0}) stat({1}) iba({2}) cba({3}) cyc({4})", workitem.index, workitem.status, workitem.inputBytesAvailable, workitem.compressedBytesAvailable, wcycles); } if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) break; } } while (true); } if (_noMoreInputForThisSegment) TraceOutput(TraceBits.Write, "Write nomore nw({0}) nf({1}) break({2})", _nextToWrite, _nextToFill, (_nextToWrite == _nextToFill)); if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) break; } while (true); // Finish: // After writing a series of buffers, closing each one with // Flush.Sync, we now write the final one as Flush.Finish, and // then stop. byte[] buffer = new byte[128]; ZlibCodec compressor = new ZlibCodec(); int rc = compressor.InitializeDeflate(_compressLevel, false); compressor.InputBuffer = null; compressor.NextIn = 0; compressor.AvailableBytesIn = 0; compressor.OutputBuffer = buffer; compressor.NextOut = 0; compressor.AvailableBytesOut = buffer.Length; rc = compressor.Deflate(FlushType.Finish); if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) throw new Exception("deflating: " + compressor.Message); if (buffer.Length - compressor.AvailableBytesOut > 0) { TraceOutput(TraceBits.WriteBegin, "Write begin flush bytes({0})", buffer.Length - compressor.AvailableBytesOut); _outStream.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut); TraceOutput(TraceBits.WriteBegin, "Write done flush"); } compressor.EndDeflate(); _Crc32 = c.Crc32Result; // signal that writing is complete: TraceOutput(TraceBits.Synch, "Synch _writingDone.Set() PWM"); _writingDone.Set(); } while (true); } catch (System.Exception exc1) { lock(_eLock) { // expose the exception to the main thread if (_pendingException!=null) _pendingException = exc1; } } TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod FINIS"); }
private void _EmitPendingBuffers(bool doAll, bool mustWait) { // When combining parallel deflation with a ZipSegmentedStream, it's // possible for the ZSS to throw from within this method. In that // case, Close/Dispose will be called on this stream, if this stream // is employed within a using or try/finally pair as required. But // this stream is unaware of the pending exception, so the Close() // method invokes this method AGAIN. This can lead to a deadlock. // Therefore, failfast if re-entering. if (emitting) { return; } emitting = true; if (doAll || mustWait) { _newlyCompressedBlob.WaitOne(); } do { int firstSkip = -1; int millisecondsToWait = doAll ? 200 : (mustWait ? -1 : 0); int nextToWrite; while (_toWrite.TryTake(out nextToWrite, millisecondsToWait)) { WorkItem workitem = _pool[nextToWrite]; if (workitem.ordinal != _lastWritten + 1) { // not the needed ordinal, so requeue and try again. TraceOutput(TraceBits.EmitSkip, "Emit skip wi({0}) ord({1}) lw({2}) fs({3})", workitem.index, workitem.ordinal, _lastWritten, firstSkip); _toWrite.Add(nextToWrite); if (firstSkip == nextToWrite) { // We went around the list once. // None of the items in the list is the one we want. // Now wait for a compressor to signal. _newlyCompressedBlob.WaitOne(); firstSkip = -1; } else if (firstSkip == -1) { firstSkip = nextToWrite; } continue; } firstSkip = -1; TraceOutput(TraceBits.EmitBegin, "Emit begin wi({0}) ord({1}) cba({2})", workitem.index, workitem.ordinal, workitem.compressedBytesAvailable); _outStream.Write(workitem.compressed, 0, workitem.compressedBytesAvailable); _runningCrc.Combine(workitem.crc, workitem.inputBytesAvailable); _totalBytesProcessed += workitem.inputBytesAvailable; workitem.inputBytesAvailable = 0; TraceOutput(TraceBits.EmitDone, "Emit done wi({0}) ord({1}) cba({2}) mtw({3})", workitem.index, workitem.ordinal, workitem.compressedBytesAvailable, millisecondsToWait); _lastWritten = workitem.ordinal; _toFill.Add(workitem.index); // don't wait next time through if (millisecondsToWait == -1) { millisecondsToWait = 0; } } } while (doAll && !_toCompress.IsCompleted && (_lastWritten != _latestCompressed)); emitting = false; }
private void _PerpetualWriterMethod(object state) { try { ZlibCodec zlibCodec; while (true) { _sessionReset.WaitOne(); if (_isDisposed) { return; } _sessionReset.Reset(); WorkItem workItem = null; CRC32 cRC = new CRC32(); bool flag; while (true) { workItem = _pool[_nextToWrite % _pc]; lock (workItem) { if (_noMoreInputForThisSegment) { } while (true) { if (workItem.status == 4) { workItem.status = 5; _outStream.Write(workItem.compressed, 0, workItem.compressedBytesAvailable); cRC.Combine(workItem.crc, workItem.inputBytesAvailable); _totalBytesProcessed += workItem.inputBytesAvailable; _nextToWrite++; workItem.inputBytesAvailable = 0; workItem.status = 6; Monitor.Pulse(workItem); break; } int num = 0; while (workItem.status != 4 && (!_noMoreInputForThisSegment || _nextToWrite != _nextToFill)) { num++; Monitor.Pulse(workItem); Monitor.Wait(workItem); if (workItem.status != 4) { } } if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } flag = true; } } if (_noMoreInputForThisSegment) { } if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) { break; } flag = true; } byte[] array = new byte[128]; zlibCodec = new ZlibCodec(); int num2 = zlibCodec.InitializeDeflate(_compressLevel, wantRfc1950Header: false); zlibCodec.InputBuffer = null; zlibCodec.NextIn = 0; zlibCodec.AvailableBytesIn = 0; zlibCodec.OutputBuffer = array; zlibCodec.NextOut = 0; zlibCodec.AvailableBytesOut = array.Length; num2 = zlibCodec.Deflate(FlushType.Finish); if (num2 != 1 && num2 != 0) { break; } if (array.Length - zlibCodec.AvailableBytesOut > 0) { _outStream.Write(array, 0, array.Length - zlibCodec.AvailableBytesOut); } zlibCodec.EndDeflate(); _Crc32 = cRC.Crc32Result; _writingDone.Set(); flag = true; } throw new Exception("deflating: " + zlibCodec.Message); } catch (Exception pendingException) { lock (_eLock) { if (_pendingException != null) { _pendingException = pendingException; } } } }