Skip to content

Commit

Permalink
Split ReadAsync into three methods.
Browse files Browse the repository at this point in the history
Avoid "await" if ReceiveReplyAsync completed synchronously (because the data was already in memory).

See dotnet/roslyn#10449 for more details.
  • Loading branch information
bgrainger committed Apr 20, 2016
1 parent ebe1dc7 commit 0449b82
Showing 1 changed file with 36 additions and 18 deletions.
54 changes: 36 additions & 18 deletions src/MySql.Data/MySqlClient/MySqlDataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,52 @@ public override bool Read()
return ReadAsync(CancellationToken.None).GetAwaiter().GetResult();
}

public override async Task<bool> ReadAsync(CancellationToken cancellationToken)
public override Task<bool> ReadAsync(CancellationToken cancellationToken)
{
VerifyNotDisposed();

// if we've already read past the end of this resultset, Read returns false
if (m_state == State.HasMoreData || m_state == State.NoMoreData)
return false;
return s_falseTask;

if (m_state != State.AlreadyReadFirstRow)
{
var payload = await m_session.ReceiveReplyAsync(cancellationToken).ConfigureAwait(false);
var payloadTask = m_session.ReceiveReplyAsync(cancellationToken);
if (payloadTask.Status == TaskStatus.RanToCompletion)
return ReadAsyncRemainder(payloadTask.Result) ? s_trueTask : s_falseTask;
return ReadAsyncAwaited(payloadTask);
}

if (payload.HeaderByte == EofPayload.Signature)
{
var eof = EofPayload.Create(payload);
m_state = eof.ServerStatus.HasFlag(ServerStatus.MoreResultsExist) ? State.HasMoreData : State.NoMoreData;
return false;
}
m_state = State.ReadingRows;
return s_trueTask;
}

var reader = new ByteArrayReader(payload.ArraySegment);
for (var column = 0; column < m_dataOffsets.Length; column++)
{
var length = checked((int) ReadFieldLength(reader));
m_dataLengths[column] = length == -1 ? 0 : length;
m_dataOffsets[column] = length == -1 ? -1 : reader.Offset;
reader.Offset += m_dataLengths[column];
}
private async Task<bool> ReadAsyncAwaited(Task<PayloadData> payloadTask)
{
var payload = await payloadTask.ConfigureAwait(false);
return ReadAsyncRemainder(payload);
}

private bool ReadAsyncRemainder(PayloadData payload)
{
if (payload.HeaderByte == EofPayload.Signature)
{
var eof = EofPayload.Create(payload);
m_state = eof.ServerStatus.HasFlag(ServerStatus.MoreResultsExist) ? State.HasMoreData : State.NoMoreData;
return false;
}

m_currentRow = payload.ArraySegment.Array;
var reader = new ByteArrayReader(payload.ArraySegment);
for (var column = 0; column < m_dataOffsets.Length; column++)
{
var length = checked((int) ReadFieldLength(reader));
m_dataLengths[column] = length == -1 ? 0 : length;
m_dataOffsets[column] = length == -1 ? -1 : reader.Offset;
reader.Offset += m_dataLengths[column];
}

m_currentRow = payload.ArraySegment.Array;

m_state = State.ReadingRows;
return true;
}
Expand Down Expand Up @@ -640,6 +655,9 @@ private enum State
NoMoreData,
}

static readonly Task<bool> s_falseTask = Task.FromResult(false);
static readonly Task<bool> s_trueTask = Task.FromResult(true);

MySqlCommand m_command;
MySqlSession m_session;
State m_state;
Expand Down

0 comments on commit 0449b82

Please sign in to comment.