goset icon indicating copy to clipboard operation
goset copied to clipboard

What about concurrency?

Open vanodevium opened this issue 3 years ago • 4 comments

We have 3 way:

  1. we have to set up mutex
  2. we can write concurrency version of methods
  3. don't use goset in concurrency functionality (so sad)

What do you prefer?


Simple test case

func TestSet_Add_Concurrency(t *testing.T) {
	s := NewSet[int]()

	var wg sync.WaitGroup
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func(i int) {
			s.Add(i)
			wg.Done()
		}(i)
	}

	wg.Wait()

	require.Equal(t, 10, s.Len())
}

Result:

=== RUN   TestSet_Add_Concurrency
fatal error: concurrent map writes

vanodevium avatar May 08 '22 16:05 vanodevium

I tend to say the prettiest way to add concurrency support is to add a concurrent-safe struct that wraps Set and adds a mutex lock before every operation (and defers an unlock). This way people who need concurrency will have a convenient solution, without hurting the performance for those who don't need concurrency.

Methods in the new struct should be pretty simple, something like that:

func (c *ConcurrencySafeSet[T]) Add(items ...T) {
	c.lock.Lock()
	defer c.lock.Unlock()
	return c.set.Add(items...)
}

WDYT?

amit7itz avatar May 14 '22 12:05 amit7itz

@amit7itz Sounds good. I can try to do this. Wait new PR :)

vanodevium avatar May 14 '22 13:05 vanodevium

@amit7itz I did. Please look at

vanodevium avatar May 14 '22 16:05 vanodevium

As discussed on the PR, right now there is no real demand for a concurrent safe Set, therefore we decided to postpone the work on this feature. I keep the issue so in case anyone ever needs this, they can comment on their use case here and we'll consider adding a concurrent safe form of Set to the project.

Until then, Set can be used together with a standard lock to ensure concurrency safety.

amit7itz avatar May 21 '22 18:05 amit7itz