synchronization - Is type assertion of a dereferenced pointer a memory write in go? -
the go race detector complains code in way makes no sense me, guess authors of race detector know more do.
i have closure:
func(f *datastore.f) bool { a, ok := (*f).(*datastore.t) ... }
that pass argument function:
func getfunc(f func(fid *datastore.f) bool) (*datastore.f, bool) { kvs.lock.rlock() defer kvs.lock.runlock() _, v := range kvs.fs { if f(v) { return v, true } } return nil, false }
and relevant part of other goroutine:
for read := range [chan of datastore.f] { s.lock.lock() s.fs[read.fi()] = &read s.lock.unlock() }
kvs
instance of type:
type kvstore struct { lock sync.rwmutex fs map[datastore.fi]*datastore.f }
datastore.f
interface, , *datastore.t
implements interface.
the race detector complains closure , other goroutine have data race. other goroutine writes , closure reads. don't see how conflict, given sync.rwmutex
in place.
a type assertion of dereferenced pointer not write variable in go.
this code
for read := range [chan of datastore.f] { s.lock.lock() s.fs[read.fi()] = &read s.lock.unlock() }
sets map value address of local variable read
. variable read
has scope outside loop block , modified on every iteration through loop. map values contain same pointer, not intended.
the closure reads the variable read
dereferencing pointer in map. race detector complains because there's no synchronization between reader (the closure) , writer (the loop).
to fix problem, declare new variable inside loop:
for read := range [chan of datastore.f] { read := read // <-- add line s.lock.lock() s.fs[read.fi()] = &read s.lock.unlock() }
with change, each map value points unique variable set once.
it rare use pointers interfaces in go. preferred fix problem change use of type *datastore.f
datastore.f
. change eliminates references the variable read
across goroutine boundaries , eliminates unnecessary level of indirection.
Comments
Post a Comment