This is a very rough proposal.
For a concurrent program, frequently calling functions in sync/atomic packages is verbose, especially for getting/setting pointer values. So how about to add a new operator @= to make atomic assignments?
I don't know how difficult to implement this, but I think this feature will be like the go keyword, to make go programs cleaner.
Atomic operations are subtle. I think that experience in other languages shows that most people can not use them correctly. Making them easy to use by putting them into the language proper is just setting traps for non-expert users. I vote strongly against this proposal. Sorry.
@ianlancetaylor,
an atomic assignment is just a simple replacement of a calling of atomic.Load/StoreXxx functions.
For example:
var a, b int64
func f() {
a @= b
a =@ b
}
will be translated to
import "sync/atomic"
var a, b int
func f() {
atomic.StoreInt64(&a, b)
a = atomic.LoadInt64(&b)
}
One advantage of using atomic assignment is we can avoid importing the unsafe package when Load/Store pointer values.
A variant of this proposal is to prefix the @ char before a variable when the variable is passed as a parameter etc.
:) just some immature ideas.
The fact that atomic operations are verbose is a feature, not a bug. To quote @dvyukov's article about "benign" data races,
Second, usage of atomic operations greatly improves code readability. Plain memory accesses and shared memory synchronization are hideously different operations, and that must be visible in the code. If a shared memory operation is as invisible in the code as simple “x->cnt++”, that will waste developers time trying to understand what actually happens in the code and lead to introduction of bugs during maintenance. Verbose atomic operations clearly say “Be extremely cautious here!”
But calling atomic functions is too verbose, especially for pointer values, in which case the unsafe.Pointer must be used.
Using @ is a good balance between verbose and visibility.
It is true that pointer reads and writes are quite verbose.
var globalP *int
p := (*int)(atomic.ReadPointer((*unsafe.Pointer)(unsafe.Pointer(&globalP))))
But I would argue the fix is generics, not atomic-specific language changes. With appropriate generics we could just do
p := atomic.ReadPointer(&globalP)
I'm going to decline this proposal per @ianlancetaylor and @randall77's comments.
Most helpful comment
Atomic operations are subtle. I think that experience in other languages shows that most people can not use them correctly. Making them easy to use by putting them into the language proper is just setting traps for non-expert users. I vote strongly against this proposal. Sorry.