Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Turn on _enableOffering in TryReceiveAll as in TryReceive #203

Merged
merged 4 commits into from
Dec 8, 2014

Conversation

i3arnon
Copy link

@i3arnon i3arnon commented Dec 6, 2014

In SourceCore TryReceive turns on enableOffering to offer the next messages to any target (if there is one) while TryReceiveAll didn't.

Fix #202

In SourceCore TryReceive turns on enableOffering to offer the next messages to any target (if there is one) while TryReceiveAll didn't.

Fix #202
@@ -351,6 +351,9 @@ internal bool TryReceiveAll(out IList<TOutput> items)
// Increment the next ID. Any new value is good.
_nextMessageId.Value++;

// Now that the next message has changed, reenable offering if it was disabled
if (!_enableOffering) _enableOffering = true;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not set it unconditionally? Surely that's faster.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any cause for concern that offering shouldn't be enabled, for example in the case of a faulted block?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree completely about the condition. It was simply copied verbatim from the TryReceive method and the guideline says to keep the original style. They can both be changed however.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About the faulted block, I don't think so since:

  1. TryReceive already has the same behaviour of increasing the _nextMessageId by one, enabling _enableOffering and calling CompleteBlockIfPossible.
  2. Completion is handled just after by CompleteBlockIfPossible and further inner calls that check _decliningPermanently and CanceledOrFaulted

@stephentoub
Copy link
Member

@i3arnon, thanks for the fix! The fix itself looks good.

The test, however, is insufficient, as the bug is due to a race condition (on my machine looping over your test before the fix, it only fails ~1% of the time). I'd suggest changing the test by wrapping up the logic before the WhenAny into a Task-returning method that returns the OutputAvailableAsync task, and then in the test method instead of setting outputAvailableAsync to a single instance, set it to something like "Task.WhenAll(Enumerable.Range(0, 1000).Select(_ => Repro()))", where Repro is the method that returns the OutputAvailableAsync task. That way, it's much more likely that we'll see the failure but without taking significantly more time for the test, as we'll be doing all of the tests effectively concurrently. Does that make sense?

As for the "if (!_enableOffering) _enableOffering = true", we can probably change all of the occurrences of this pattern in this block to just be "_enableOffering = true". I don't remember now why we thought this was a good idea (maybe something related to invalidating cache lines, though that doesn't look particularly relevant here), and some quick tests just now show no benefit from the extra check.

@i3arnon
Copy link
Author

i3arnon commented Dec 7, 2014

Thanks @stephentoub, I've reimplemented the test as you suggested and replaced all the conditional sets of _enableOffering with unconditional ones. //cc: @AArnott

Assert.True(completedTask != timeoutTask);
}

private Task GetOutputAvailableAsyncTaskAfterTryReceiveAllOnNonEmptyBufferBlock()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also be done as a lambda to keep it inside of the corresponding [Fact] method, but I'm ok with it as is.

@stephentoub
Copy link
Member

Thanks for making the changes to the test. LGTM.

@stephentoub stephentoub added the bug Product bug (most likely) label Dec 8, 2014
stephentoub added a commit that referenced this pull request Dec 8, 2014
Turn on _enableOffering in TryReceiveAll as in TryReceive
@stephentoub stephentoub merged commit 1b54243 into dotnet:master Dec 8, 2014
@i3arnon i3arnon deleted the BufferBlockBug branch December 8, 2014 08:55
@karelz karelz modified the milestone: 1.0.0-rtm Dec 3, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Product bug (most likely)
Projects
None yet
4 participants