Closed pancl1411 closed 3 years ago
I believe this comment was originally added in CL 37342, and it also exists in golang.org/x/sync/syncmap
.
CC @bcmills in case this is still familiar to you.
LoadAndDelete
itself was added recently (in CL 205899, with a subsequent fix in CL 250197).
At any rate, I think you are correct that it is possible for p == nil
when m.dirty != nil
. Perhaps the comment should read:
// If p == nil, the entry has been deleted, and either m.dirty == nil or
// m.dirty[key] is e.
@pancl1411, does that seem more correct to you?
CC @changkun
I just revisited the code. The described execution flow had already existed in the old Delete
implementation before LoadAndDelete
CLs. I think I didn't pay too much attention to the comments in entry
while introducing LoadAndDelete.
Not entirely sure why the comment was in that way but I have a theory:
If the entry has been deleted, then the future m.read
access of the key can lead to delete
of that key in the dirty map, and trigger missLocked
, which eventually have: m.dirty == nil
before the next write (sync.Map is designed for high-read low-write).
If that is the case, then we don't need change anything; otherwise I think the proposed comments is the right fix. What do you think?
I think it's probably a good idea to update the comment. (It should describe invariants that are always satisfied, not just conditions that will eventually be satisfied.)
@changkun I totally agree with your thoery, it sounds reasonable, so we don't need change anything except update comments.
@bcmills the comment you update is good enough for me:
// If p == nil, the entry has been deleted, and either m.dirty == nil or
// m.dirty[key] is e.
thank you all for detailed analysis and promptly apply, so should I commit this as a pull request?
Change https://golang.org/cl/308292 mentions this issue: sync: update misleading comment in map.go about entry type
I noticed the comment in the golang.org/x/sync/syncmap
package is in a pre_go19.go
file, since after Go 1.9 it just does type Map = sync.Map
. So it's probably not a big deal to leave it as is.
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
1) the misleading comment i think: the misleading comment line about entry type while p == nil, as follows:
in entry type:
2) the source code logic i understand:
sync.Map
has some valid key in bothread.m
anddirty
map (which is common, and meansdirty != nil
);LoadAndDelete
to delete one of these vaild key;func (e entry) delete() (value interface{}, ok bool) { for { p := atomic.LoadPointer(&e.p) if p == nil || p == expunged { return nil, false } // (4) set entry.p == nil, but this time has m.dirty != nil if atomic.CompareAndSwapPointer(&e.p, p, nil) {
return (*interface{})(p), true } } }
p == nil
withm.dirty != nil
What did you expect to see?
code comments should cover all cases, but this one it seems not, am i misunderstand?
What did you see instead?
in code comment, If
p == nil
withm.dirty == nil
, but sometimesp == nil
withm.dirty != nil
.Additional
I am new to use golang, and not sure if I understand this correctly, so let me know if i am wrong.
thanks a lot!