-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
In June 2021 I posted a series of articles about memory models, ending with an article about changes I thought we should make to the Go memory model. See https://research.swtch.com/mm especially https://research.swtch.com/gomm.
Then I opened a GitHub Discussion to discuss these changes; see #47141.
Based on that discussion, I propose to add the following types to sync/atomic: Bool, Int32, Int64, Uint32, Uint64, Uintptr, Pointer[T any].
These have methods appropriate to the type. They all have Load, Store, Swap, and CompareAndSwap methods. The integers also have an Add method (Bool and Pointer[T] do not).
The exact details can be viewed in pending CL 381317 prepared for concreteness.
I have filed a separate proposal, #50859, for documentation fixes arising from the June discussion.
Generics? A natural question is why the types are not something like atomic.Val[bool], atomic.Val[int32], and so on. The main answer is that the APIs are different for different types, and generics provides no way to accomplish that.
Specifically, Bool and Pointer[T] should not have an Add method, while the integers should.
Another reason is that there is no way to write a single constraint that works for this set of types. The way to write a generic pointer constraint, for atomic.Val[*byte], is to say [T ~*E, E any], but there is no way to add on the other types. If we do
type Val[T interface { ~*E | ~bool | ~int32 | ... }, E any] struct { ... }
then any use that infers bool, int32, or so on for T will not have any idea what to infer for E, requiring the programmer to write
atomic.Val[bool, DOESNOTMATTER]
where DOESNOTMATTER is any type at all. All in all, trying to use generics is pretty awkward here.
Uses are awkward too: atomic.Val[int32] is not as nice as plain atomic.Int32.
We could potentially introduce a single generic for the ints, as in atomic.Int[int32], but that removes awkwardness in the implementation at the cost of introducing awkwardness (repetition) at all the call sites. That's usually the wrong tradeoff, including here.
(Finally there is the matter of what the implementation body would look like in the generic functions, but all the preceding concerns prevent us from even reaching that one.)
The non-generic API is simpler to explain and easier to use.