What about concurrency?
We have 3 way:
- we have to set up mutex
- we can write concurrency version of methods
- 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
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 Sounds good. I can try to do this. Wait new PR :)
@amit7itz I did. Please look at
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.