/// <summary>
        ///   Constructs a new <c>ParallelBZip2OutputStream</c> with specified blocksize,
        ///   and explicitly specifies whether to leave the wrapped stream open.
        /// </summary>
        ///
        /// <param name = "output">the destination stream.</param>
        /// <param name = "blockSize">
        ///   The blockSize in units of 100000 bytes.
        ///   The valid range is 1..9.
        /// </param>
        /// <param name = "leaveOpen">
        ///   whether to leave the captive stream open upon closing this stream.
        /// </param>
        public ParallelBZip2OutputStream(Stream output, int blockSize, bool leaveOpen)
        {
            if (blockSize < BZip2.MinBlockSize || blockSize > BZip2.MaxBlockSize)
            {
                var msg = String.Format("blockSize={0} is out of range; must be between {1} and {2}",
                                        blockSize,
                                        BZip2.MinBlockSize, BZip2.MaxBlockSize);
                throw new ArgumentException(msg, "blockSize");
            }

            this.output = output;
            if (!this.output.CanWrite)
            {
                throw new ArgumentException("The stream is not writable.", "output");
            }

            this.bw            = new BitWriter(this.output);
            this.blockSize100k = blockSize;
            this.leaveOpen     = leaveOpen;
            this.combinedCRC   = 0;
            this.MaxWorkers    = 16; // default
            EmitHeader();
        }
        /// <summary>
        ///   Close the stream.
        /// </summary>
        /// <remarks>
        ///   <para>
        ///     This may or may not close the underlying stream.  Check the
        ///     constructors that accept a bool value.
        ///   </para>
        /// </remarks>
        public override void Close()
        {
            if (this.pendingException != null)
            {
                this.handlingException = true;
                var pe = this.pendingException;
                this.pendingException = null;
                throw pe;
            }

            if (this.handlingException)
            {
                return;
            }

            if (output == null)
            {
                return;
            }

            Stream o = this.output;

            try
            {
                FlushOutput(true);
            }
            finally
            {
                this.output = null;
                this.bw     = null;
            }

            if (!leaveOpen)
            {
                o.Close();
            }
        }
 private void EmitPendingBuffers(bool doAll, bool mustWait)
 {
     if (this.emitting)
     {
         return;
     }
     this.emitting = true;
     if (doAll || mustWait)
     {
         this.newlyCompressedBlob.WaitOne();
     }
     do
     {
         int num  = -1;
         int num2 = (!doAll) ? ((!mustWait) ? 0 : -1) : 200;
         int num3 = -1;
         do
         {
             if (Monitor.TryEnter(this.toWrite, num2))
             {
                 num3 = -1;
                 try
                 {
                     if (this.toWrite.Count > 0)
                     {
                         num3 = this.toWrite.Dequeue();
                     }
                 }
                 finally
                 {
                     Monitor.Exit(this.toWrite);
                 }
                 if (num3 >= 0)
                 {
                     WorkItem workItem = this.pool[num3];
                     if (workItem.ordinal != this.lastWritten + 1)
                     {
                         object obj = this.toWrite;
                         lock (obj)
                         {
                             this.toWrite.Enqueue(num3);
                         }
                         if (num == num3)
                         {
                             this.newlyCompressedBlob.WaitOne();
                             num = -1;
                         }
                         else if (num == -1)
                         {
                             num = num3;
                         }
                     }
                     else
                     {
                         num = -1;
                         BitWriter bitWriter = workItem.bw;
                         bitWriter.Flush();
                         MemoryStream ms = workItem.ms;
                         ms.Seek(0L, SeekOrigin.Begin);
                         long   num4  = 0L;
                         byte[] array = new byte[1024];
                         int    num5;
                         while ((num5 = ms.Read(array, 0, array.Length)) > 0)
                         {
                             for (int i = 0; i < num5; i++)
                             {
                                 this.bw.WriteByte(array[i]);
                             }
                             num4 += (long)num5;
                         }
                         if (bitWriter.NumRemainingBits > 0)
                         {
                             this.bw.WriteBits(bitWriter.NumRemainingBits, (uint)bitWriter.RemainingBits);
                         }
                         this.combinedCRC           = (this.combinedCRC << 1 | this.combinedCRC >> 31);
                         this.combinedCRC          ^= workItem.Compressor.Crc32;
                         this.totalBytesWrittenOut += num4;
                         bitWriter.Reset();
                         this.lastWritten = workItem.ordinal;
                         workItem.ordinal = -1;
                         this.toFill.Enqueue(workItem.index);
                         if (num2 == -1)
                         {
                             num2 = 0;
                         }
                     }
                 }
             }
             else
             {
                 num3 = -1;
             }
         }while (num3 >= 0);
     }while (doAll && this.lastWritten != this.latestCompressed);
     if (doAll)
     {
     }
     this.emitting = false;
 }