Thanks, Skip. That fixes it. Is the need for a pointer receiver documented 
somewhere? It's not something that even crossed my mind given that the 
neither the compiler nor golint complained.  I suppose it makes sense if I 
think of func (x) foo(y) {} as being an alternate way of writing func 
foo(x, y) {}. In that case, it's clear that a copy of x is being passed 
since that's Go's default.

While this topic is still alive, I'd like to ask a follow-on question: Is 
the use of sync/atomic actually needed in this example or is it sufficient 
to wrap all accesses in mutex Lock/Unlock (using the same mutex, of course).

  

On Sunday, April 14, 2019 at 12:08:55 PM UTC-4, Skip wrote:
>
> The receiver for load and update should be the original object not a copy.
>
> https://play.golang.org/p/XCZC0OVhGMa
>
> On Sun, Apr 14, 2019, 7:56 AM <michae...@gmail.com <javascript:>> wrote:
>
>>
>> https://play.golang.org/p/6aQYNjojyBD
>>
>> I'm clearly missing something about the way sync.Mutex and atomic.Value 
>> work in Go.
>>
>> I'm attempting to write a pair of concurrency safe methods, load() and 
>> update(), for accessing a struct.  The struct is stored as an atomic.Value 
>> and accessed with atomic.Load and atomic.Value.  I'm also wrapping the 
>> accesses within a mutex Lock/Unlock.  That's probably unneeded for my 
>> load() method but I added it trying to figure out why it's not returning 
>> updated info. In my minimal example below (also in the Go Playground link 
>> above) the output of main() should be:
>>
>> s={65535}
>> v={65535}
>>
>> but I get
>>
>> s={65535}
>> v={0}
>>
>> indicating that the updated value is not available after the call to 
>> update().
>>
>> The only thing I'm doing that's a little different from the examples in 
>> the doc for sync/atomic is passing a function that takes a pointer to a 
>> struct instance to my update function. I do that to make it easy to write 
>> code that updates just a few items in the state struct (which in my real 
>> application has many members instead of just one as shown here.)
>>
>> Apologies for wasting the group's time if I've overlooked a brain-dead 
>> error, but I've been fooling with this for several hours now and can't see 
>> why it shouldn't be working,   
>>
>>
>> package main
>>
>> import (
>> "fmt"
>> "sync"
>> "sync/atomic"
>> )
>>
>> type state struct {
>> R4000 uint16
>> }
>> type guardedState struct {
>> v atomic.Value
>> }
>>
>> var stateMutex = sync.Mutex{}
>> var gState guardedState
>>
>> func init() {
>> gState.v.Store(state{})
>> }
>>
>> func (g guardedState) load() state {
>> stateMutex.Lock()
>> defer stateMutex.Unlock()
>> s := gState.v.Load()
>> return s.(state)
>> }
>>
>> func (g guardedState) update(f func(*state)) {
>> stateMutex.Lock()
>> defer stateMutex.Unlock()
>> s := g.v.Load().(state)
>> f(&s)
>> g.v.Store(s)
>> }
>>
>> func main() {
>> f := func(s *state) {
>> s.R4000 = 65535
>> fmt.Printf("s=%v\n", *s)
>> }
>> gState.update(f)
>> v := gState.load()
>> fmt.Printf("v=%v\n", v)
>> }
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golan...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to