-
Notifications
You must be signed in to change notification settings - Fork 772
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a value type version of CircularBuffer #1325
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1325 +/- ##
=========================================
Coverage ? 76.54%
=========================================
Files ? 224
Lines ? 6471
Branches ? 0
=========================================
Hits ? 4953
Misses ? 1518
Partials ? 0
|
{ | ||
// If we got here it means a writer isn't done. | ||
continue; | ||
} | ||
|
||
this.trait[index] = null; | ||
// TODO: we are doing an extra copy from the buffer, this can be optimized if Read() could take a callback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it would help to use ref return here? Something like this...
public ref T Read()
{
var value = this.trait[index].Value;
this.trait[index].Value = default(T);
this.trait[index].IsReady = false;
this.tail++;
return ref value;
}
If T is readonly struct, compiler might be smart enough to do that automatically.
For max perf this might also work...
public ref T Read()
{
ref var value = ref this.trait[index].Value;
// this.trait[index].Value = default(T); <- Not sure if this will clobber the ref or not.
this.trait[index].IsReady = false;
this.tail++;
return ref value;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once this.tail++
happened, other writer threads have the freedom to overwrite the struct value, which will cause race condition if the reader hasn't finished consuming the struct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH, not sure. This is fringe stuff I only rarely get a chance to use 😄 I had a mistake in the first snippet, updated now. I removed a ref that shouldn't have been in there. The first snippet I think is safe. It makes a copy from the array, and then returns that copy by ref to the caller. At best, saves one copy. Second snippet might have a race. There are strict rules with ref locals, caller has to also use it as a local. So it will be extremely short-lived, but yes there could be an issue if the buffer loops around really quickly. Maybe we go as-is and then we can try to perf hack it while you continue on with the real effort?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I bet the 1st one is covered by NRV (named return value) optimization 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Related to #1315.
To make it easier, please review the 2nd commit which has the diff (the 1st commit is a direct copy of the existing CircularBuffer).
Changes
For significant contributions please make sure you have completed the following items:
CHANGELOG.md
updated for non-trivial changes