public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        {
            this.EnsureOpened();
            this.IncrementAsyncWriteCount();

            Fx.Assert(this.writeState == null ||
                      this.writeState.Arguments == null ||
                      this.writeState.Arguments.Count <= 0,
                      "All data has not been written yet.");

            if (onWriteCallback == null)
            {
                onWriteCallback      = new AsyncEventArgsCallback(OnWriteCallback);
                onAsyncFlushComplete = new AsyncEventArgsCallback(OnAsyncFlushComplete);
            }

            if (this.writeState == null)
            {
                this.writeState = new WriteAsyncState();
                this.writeArgs  = new WriteAsyncArgs();
            }
            else
            {
                // Since writeState!= null, check if the stream has an
                // exception as the async path has already been invoked.
                this.ThrowOnException();
            }

            this.writeArgs.Set(buffer, offset, count, callback, state);
            this.writeState.Set(onWriteCallback, this.writeArgs, this);
            if (this.WriteAsync(this.writeState) == AsyncCompletionResult.Completed)
            {
                this.writeState.Complete(true);
                if (callback != null)
                {
                    callback(this.writeState.CompletedSynchronouslyAsyncResult);
                }

                return(this.writeState.CompletedSynchronouslyAsyncResult);
            }

            return(this.writeState.PendingAsyncResult);
        }
        AsyncCompletionResult WriteAsync(WriteAsyncState state)
        {
            Fx.Assert(state != null && state.Arguments != null, "Invalid WriteAsyncState parameter.");

            if (state.Arguments.Count == 0)
            {
                return(AsyncCompletionResult.Completed);
            }

            byte[] buffer = state.Arguments.Buffer;
            int    offset = state.Arguments.Offset;
            int    count  = state.Arguments.Count;

            ByteBuffer currentBuffer = this.GetCurrentBuffer();

            while (count > 0)
            {
                if (currentBuffer == null)
                {
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(SR.WriteAsyncWithoutFreeBuffer)));
                }

                int freeBytes = currentBuffer.FreeBytes;   // space left in the CurrentBuffer
                if (freeBytes > 0)
                {
                    if (freeBytes > count)
                    {
                        freeBytes = count;
                    }

                    currentBuffer.CopyData(buffer, offset, freeBytes);
                    offset += freeBytes;
                    count  -= freeBytes;
                }

                if (currentBuffer.FreeBytes == 0)
                {
                    this.DequeueAndFlush(currentBuffer, onAsyncFlushComplete);

                    // We might need to increase the number of buffers available
                    // if there is more data to be written or no buffer is available.
                    if (count > 0 || this.buffers.Count == 0)
                    {
                        this.AdjustBufferSize();
                    }
                }

                //Update state for any pending writes.
                state.Arguments.Offset = offset;
                state.Arguments.Count  = count;

                // We can complete synchronously only
                // if there a buffer available for writes.
                currentBuffer = this.GetCurrentBuffer();
                if (currentBuffer == null)
                {
                    if (this.buffers.TryUnlock())
                    {
                        return(AsyncCompletionResult.Queued);
                    }

                    currentBuffer = this.GetCurrentBuffer();
                }
            }

            return(AsyncCompletionResult.Completed);
        }
 internal PooledAsyncResult(WriteAsyncState parentState, bool completedSynchronously)
 {
     this.writeState             = parentState;
     this.completedSynchronously = completedSynchronously;
 }