private void copy_io_stream_async(CopyStreamItem item)
        {
            if (buffer_sync == null)
            {
                buffers_async = new StreamAsyncWriter();
                buffers_async.WriteChunkCallback = new WriteChunk(write_chunk_finish_async);
                buffers_async.PrepareBuffers(buffers_count, buffer_size);
            }

            int  bytes_readed  = 0;
            bool continue_copy = true;

            while (continue_copy)
            {
                StreamWriterBuffer buf = buffers_async.WaitForFreeBuffer();
                bytes_readed          = item.SourceStream.Read(buf.buffer, 0, buffer_size);
                buf.ActualBytes       = bytes_readed;
                buf.DestinationStream = item.DestinationStream;
                buf.DestinationName   = item.DestinationName;
                buffers_async.Enqueue(buf);

                //notify chunk read finish

                continue_copy = bytes_readed != 0;
            }
        }
        public void Dispose()
        {
            //add to write queue buffer with destination_stream=null
            //when write thread dequeue such buffer, write thread terminates
            StreamWriterBuffer fake_buffer = new StreamWriterBuffer(0);

            Enqueue(fake_buffer);
        }
 private void ReleaseBuffer(StreamWriterBuffer chunk)
 {
     lock (queue_free_lock)
     {
         queue_free.Enqueue(chunk);
     }
     wait_queue_free_ready.Set();
 }
 public void Enqueue(StreamWriterBuffer chunk)
 {
     lock (queue_write_lock)
     {
         queue_write.Enqueue(chunk);
     }
     //allow write thread proceed
     wait_queque_write_ready.Set();
 }
 public void PrepareBuffers(int buffers_count, int buffer_size)
 {
     for (int i = 0; i < buffers_count; i++)
     {
         StreamWriterBuffer new_buf = new StreamWriterBuffer(buffer_size);
         lock (queue_free_lock)
         {
             queue_free.Enqueue(new_buf);
         }
     }
     wait_queue_free_ready.Set();
 }
        private StreamWriterBuffer WaitForReadyBuffer()
        {
            wait_queque_write_ready.Reset();
            StreamWriterBuffer ret = null;

            if (ActiveBuffersCount == 0)
            {
                wait_queque_write_ready.WaitOne();
            }
            lock (queue_write_lock)
            {
                ret = queue_write.Dequeue();
            }
            return(ret);
        }
        public StreamWriterBuffer WaitForFreeBuffer()
        {
            wait_queue_free_ready.Reset();
            if (FreeBuffersCount == 0)
            {
                wait_queue_free_ready.WaitOne();
            }
            StreamWriterBuffer ret = null;

            lock (queue_free_lock)
            {
                ret = queue_free.Dequeue();
            }
            return(ret);
        }
 private void internal_write()
 {
     while (true)
     {
         StreamWriterBuffer chunk = WaitForReadyBuffer();
         if (chunk.DestinationStream == null)
         {
             break;
         }
         chunk.DestinationStream.Write(chunk.buffer, 0, chunk.ActualBytes);
         ReleaseBuffer(chunk);
         if (WriteChunkCallback != null)
         {
             WriteChunkCallback(chunk.DestinationName, chunk.ActualBytes);
         }
     }//end while
 }