-
Notifications
You must be signed in to change notification settings - Fork 2
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
feat: port context-aware cond to gobox #325
base: main
Are you sure you want to change the base?
Conversation
I've been using this for a few months in polaroid (non-generic version), so I figured it's reasonable at this point to port it to GoBox,
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.
Comments / suggestions.
because Jesse was worried about extra allocations, I aded a couple of benchmarks which also revealed a race that could result in an NPE: ``` BenchmarkCond BenchmarkCond/one_broadcasts;_one_wait BenchmarkCond/one_broadcasts;_one_wait-10 100 11171022 ns/op 1.170 ms_corrected/op 489 B/op 9 allocs/op BenchmarkCond/one_broadcasts;_many_waiters BenchmarkCond/one_broadcasts;_many_waiters-10 100 11239043 ns/op 1.230 ms_corrected/op 2023 B/op 37 allocs/op PASS ```
because Jesse was worried about extra allocations, I aded a couple of benchmarks which also revealed a race that could result in an NPE:
|
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.
Mostly LGTM! One small bug and a couple of comment suggestions.
// a condition, and releasing the lock before waiting for a state change if the condition is not met. | ||
type Cond struct { | ||
pointer atomic.Pointer[chan struct{}] | ||
Mu sync.Mutex |
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.
Document public field?
t := make(chan struct{}) | ||
c.pointer.CompareAndSwap(nil, &t) | ||
return t |
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.
This doesn't handle the race where two threads enter this if block at the same time. You should return the value of c.pointer.Load()
here (although technically only needed if CompareAndSwap
returns false
).
Correct verbose version:
t := make(chan struct{}) | |
c.pointer.CompareAndSwap(nil, &t) | |
return t | |
t := make(chan struct{}) | |
if c.pointer.CompareAndSwap(nil, &t) { | |
return t | |
} | |
return c.pointer.Load() |
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.
Probably should close t
in my example before line 35.
} | ||
} | ||
|
||
// WaitForCondition acquires Cond's lock, then checks if the condition is true. If the condition is not true, |
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.
Clarify what the lock actually is (and use the receiver name):
// WaitForCondition acquires Cond's lock, then checks if the condition is true. If the condition is not true, | |
// WaitForCondition acquires c.Mu, then checks if the condition is true. If the condition is not true, |
// This method encapsulates the instructions in sync.Cond.Wait: | ||
// | ||
// """ | ||
// Because c.L is not locked while Wait is waiting, the caller |
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.
Update L
to Mu
throughout the example?
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.
yah, thanks!
Co-authored-by: Jesse Kinkead <jesse.kinkead@outreach.io>
Co-authored-by: Jesse Kinkead <jesse.kinkead@outreach.io>
I've been using this for a few months in polaroid (non-generic version), so I figured it's reasonable at this point to port it to GoBox,
What this PR does / why we need it
Jira ID
I didn't make a ticket for this because I'm really just trying to be a good citizen here, this isn't part of feature work or anything.
[XX-XX]
Notes for your reviewers