-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
sync/atomic: add (*Value).Swap and (*Value).CompareAndSwap #39351
Comments
Thanks for the pointers; I did look, but it appears searching is hard with the wrong keywords. One thing that is not called out in the linked tickets is the warning on the
|
In my case, I need atomic.Swap because I have a variable that collects batched statistics (many go routines write to it), and one go routine is responsible of replacing that batch with a new empty batch atomically and export the old one. I had to use atomic.SwapPointer to swap and atomic.LoadPointer to get it from the writers because Mutexes had too much lock contention. |
I don't understand this comment. |
I do think there might be some value in a |
Note that #20164 specifically calls out avoidance of Also note that both #20164 and #26728 were withdrawn for lack of compelling concrete use-cases, so it would be very helpful to see some concrete examples of where the proposed method would be used. |
That is fair and I may have gotten carried away with being compatible to
While the above is called out, it felt like a preference and did not mention the non-portable and compatibility implications. My apologies if this was obvious subtext in #20164.
This was submitted on behalf of @oguzyildiz1991's use case. Let me know if more detail would be beneficial. Was the resolution of other tickets that |
The resolution on #26728 said:
Is there a new real-world use case where Value.Swap is helpful? |
how about the one I described above? @rsc |
My concern is less about the inability to use |
@carnott-snap, if you're worried about formal compatibility policies in conjunction with |
While I am now also concerned about the exact details of the To be clear, I am arguing that using |
@carnott-snap I want to clarify that nothing is going to go wrong if you convert in and out of |
That is not what the package documentation states. If it should be updated, that is fine, but it is stated in no uncertain terms:
|
I agree that unsafe is risky in a formal sense. I even tried to say that. I am saying that in practice nothing is going to go wrong if you convert in and out of If you can only accept a formal policy, then you will presumably continue to avoid unsafe. But I"m not sure that that in itself is a strong enough reason for us to add a new method to |
Thanks for the full context. As this was lost on me, I still think there is room to improve the package documentation wording to indicate this, but I respect that the flavour may be lost on other readers. Is it worth trying to improve the wording, or does everybody agree this is the best message to send to potential unsafe consumers? |
@ianlancetaylor while that is true, it limits people in way, for example I had to completely move from App Engine for multiple projects because they refuse any app with unsafe (or syscall) outside the stdlib. Adding Also having it in the stdlib would allow compiler intrinsic later on to make it more optimized and supported on the platforms that doesn't allow unsafe. |
My understanding is that App Engine no longer has that constraint. |
I haven't tried in a few years, but at least it's in their official FAQ I linked above. |
I can confirm that documentation is woefully out of date: |
I don't fully understand how all the writers are coordinating in #39351 (comment), but looking at the sync/atomic API, it does seem odd that we have Load, Store, Swap, and CompareAndSwap for all the integer types and unsafe.Pointer, but then we only have Load and Store for Value. I'm trying to remember whether there was an implementation reason for leaving them out. With the dynamic constraint that the underlying concrete type of the stored interface can't change, it should just be a plain single-word swap/cas. Unless there's some implementation subtlety I'm missing, it sounds like maybe we should add them. Thoughts? |
The API is a bit cumbersome. In order to do Swap/CompareAndSwap, you have to allocate a
|
|
@randall77, I was expecting
and
preserving the constraints that Value.Store itself has (underlying type can't change, new cannot be nil). If we preserve the constraints of Value.Store, is there any implementation difficulty with Swap and CompareAndSwap? |
I think they are doable. Swap is straightforward using CompareAndSwap is quite a bit more complicated.
|
@randall77: I am onboard with this modification to my initial proposal and will fixup the description to match. |
Based on the discussion above, this seems like a likely accept. |
No change in consensus, so accepted. |
I thought it might be worth mentioning that if/when generics come along, it's easy to make the atomic.*Pointer functions type-safe, although they'd need new names: For example:
|
Change https://golang.org/cl/241678 mentions this issue: |
if type of swap value is different, panic happened in CompareAndSwapPointer function, I don't think we need to deal with it again. |
@litao-2071 I don't understand what you're trying to say. |
Between a recent use case, and previous tickets (#11260, #20164, #26728), there is renewed interest in implementing
Swap
andCompareAndSwap
forsync/atomic.Value
.The new interface serves to be more ergonomic, eschew the use of
unsafe
, and makeatomic.Value
have parity with theatomic.XxxPointer
methods. There are some key differences between how theatomic.Value.XxxSwap
andatomic.XxxSwapPointer
work, e.g. panic on inconsistent types or nil, but these are fundamental to howatomic.Value
works, and thus an accepted complexity.Interface definition follows:
The text was updated successfully, but these errors were encountered: