Junfei Hu
Junfei Hu

Reputation: 19

Atomic operation on defined type

If I define a new type of 'State' like this:

type State int32

Could the value of type 'State' be applied with atomic operations, like 'atomic.StoreInt32()'?

If not, why?

If can, could it be applied as below?

func SetAndGet(s State, n State) State {
    si := int32(s)
    ni := int32(n)
    return State(atomic.SwapInt32(&si, ni))
}

Update:

The code is modified as below, according to @icza's answer.

func SetAndGetState(s *State, n State) State {
    return State(atomic.SwapInt32((*int32)(s), int32(n)))
}
func SetAndGetInt(s *int32, n int32) State {
    return State(atomic.SwapInt32((*int32)(s), int32(n)))
}
var s1 State = 1
var i1 int32 = 1
SetAndGetState(&s1, 2)
SetAndGetInt(&i1, 2)

I've tried the codes of mine and @icza's. And they all succeed. The result of 'State' seem to be the same as int32. What I want to know is: In high concurrency situation, does the atomic operations have the same concurrency effect on defined type 'State' as on 'int32'?

Upvotes: 0

Views: 974

Answers (1)

icza
icza

Reputation: 418227

Atomic operations are usually performed on a variable.

When you call a function, the values passed are copied. There is no reason to perform atomic operation on your local variables (function parameters) used only by your function.

You may want to perform atomic operations e.g. on a global variable. And for SetAndGet() to be able to do that, you have to pass its address (passing its value just copies it).

And you can't create a local copy of the pointer passed (neither the pointed value), you have to pass the address you get directly to atomic.SwapInt32(). And to be able to do that, simply convert the *State pointer to *int32. This is possible because State has int32 as its underlying type:

func SetAndGet(s *State, n State) State {
    return State(atomic.SwapInt32((*int32)(s), int32(n)))
}

Testing it:

var s State

func main() {
    fmt.Println(SetAndGet(&s, 1))
    fmt.Println(SetAndGet(&s, 2))
    fmt.Println(SetAndGet(&s, 3))
}

Output (try it on the Go Playground):

0
1
2

Using the above solution, you get the same concurrency guarantees as you would if you would be using int32 instead of State.

Upvotes: 3

Related Questions