-
Notifications
You must be signed in to change notification settings - Fork 60
api: replaced Future.done with a sync.Cond #508
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
base: master
Are you sure you want to change the base?
Conversation
dd9e78b to
f5ce75f
Compare
oleg-jukovec
left a comment
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.
Thanks for the patch. Overall, everything's fine.
I've added some implementation notes, but you need to do a proper rebase first.
|
Please, rebase on the master branch. |
f5ce75f to
d238853
Compare
oleg-jukovec
left a comment
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.
Thank you for the patch! I have just a one mirror comment:
d238853 to
948fcee
Compare
oleg-jukovec
left a comment
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.
Thank you for the patch!
future.go
Outdated
| resp Response | ||
| err error | ||
| cond sync.Cond | ||
| finished atomic.Bool |
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.
Right now atomic.finished is called under lock everywhere (except isDone), that is once or twice called without it. It's better to replace with simple bool calling it with lock, than making it atomic (that will invalidate cache record on every access to this variable).
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.
Done. Thanks for recommendations! I wrapped finished in connection.go like:
fut.mutex.Lock()
is_done := fut.finished
fut.mutex.Unlock()
if is_done {
...
return
}
future.go
Outdated
| fut.done = nil | ||
| fut.finished.Store(false) | ||
| fut.cond = *sync.NewCond(&fut.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.
This kind of initialization is allowed (and preferred) when sync.Cond is stored by value rather than as a pointer:
| fut.done = nil | |
| fut.finished.Store(false) | |
| fut.cond = *sync.NewCond(&fut.mutex) | |
| fut.done = nil | |
| fut.finished.Store(false) | |
| fut.cond.L = &fut.Mutex |
Moreover, it generates less code, is more performant, and helps the Go escape analyzer understand that the allocated memory does not escape (not that the analyzer couldn’t deduce this on its own, but the hint certainly doesn’t hurt).
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.
Fixed.
948fcee to
da9ec89
Compare
This commit reduces allocations. Future.done allocation replaced with - Future.cond (sync.Cond) - Future.finished (bool) Other code use `Future.finished` instead `Future.done == nil` check. Added Future.finish() marks Future as done. Future.WaitChan() now creates channel on demand. Closes #496
da9ec89 to
364deec
Compare
This commit reduces allocations.
Future.done allocation replaced with
Other code use
Future.isDone()insteadFuture.done == nilcheck.Added Future.finish() marks Future as done.
Future.WaitChan() now creates channel on demand.
Closes #496