Skip to content

There may be a bug in GetOrInsert #81

@ssfyn

Description

@ssfyn

Describe the bug
When multiple coroutines call GetOrInsert at the same time, data may be missed during Range query.

To Reproduce

func main() {
	m := hashmap.New[string, bool]()
	wg := sync.WaitGroup{}
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		kk := strconv.Itoa(i)
		go func() {
			m.GetOrInsert(kk, true)
			wg.Done()
		}()
	}
	wg.Wait()
	tmp := make([]string, 0)
	m.Range(func(key string, value bool) bool {
		tmp = append(tmp, key)
		return true
	})
	log.Println(len(tmp), "/",  m.Len()) // print: 9XX / 1000
}

Expected behavior
Return data correctly

System (please complete the following information):

  • OS: macos / linux
  • Version / Commit: 1.0.8

Additional context
When called repeatedly, Len() may be larger than the actual length.

func main() {
	m := hashmap.New[string, bool]()
	wg := sync.WaitGroup{}
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		kk := strconv.Itoa(i)
		go func() {
			m.GetOrInsert(kk, true) // call
			m.GetOrInsert(kk, true) // repeat call
			m.GetOrInsert(kk, true) // repeat call
			m.GetOrInsert(kk, true) // repeat call
			wg.Done()
		}()
	}
	wg.Wait()
	tmp := make([]string, 0)
	m.Range(func(key string, value bool) bool {
		tmp = append(tmp, key)
		return true
	})
	log.Println(m.Len()) // m.Len() may be > 1000
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions