Skip to content

Commit 1d4478f

Browse files
blueledeckarep
authored andcommitted
add Each method
1 parent b3af78e commit 1d4478f

File tree

6 files changed

+121
-0
lines changed

6 files changed

+121
-0
lines changed

bench_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,44 @@ func BenchmarkUnion100Unsafe(b *testing.B) {
501501
benchUnion(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
502502
}
503503

504+
func benchEach(b *testing.B, n int, s Set) {
505+
nums := nrand(n)
506+
for _, v := range nums {
507+
s.Add(v)
508+
}
509+
510+
b.ResetTimer()
511+
for i := 0; i < b.N; i++ {
512+
s.Each(func(elem interface{}) bool {
513+
return false
514+
})
515+
}
516+
}
517+
518+
func BenchmarkEach1Safe(b *testing.B) {
519+
benchEach(b, 1, NewSet())
520+
}
521+
522+
func BenchmarkEach1Unsafe(b *testing.B) {
523+
benchEach(b, 1, NewThreadUnsafeSet())
524+
}
525+
526+
func BenchmarkEach10Safe(b *testing.B) {
527+
benchEach(b, 10, NewSet())
528+
}
529+
530+
func BenchmarkEach10Unsafe(b *testing.B) {
531+
benchEach(b, 10, NewThreadUnsafeSet())
532+
}
533+
534+
func BenchmarkEach100Safe(b *testing.B) {
535+
benchEach(b, 100, NewSet())
536+
}
537+
538+
func BenchmarkEach100Unsafe(b *testing.B) {
539+
benchEach(b, 100, NewThreadUnsafeSet())
540+
}
541+
504542
func benchIter(b *testing.B, n int, s Set) {
505543
nums := nrand(n)
506544
for _, v := range nums {

set.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ type Set interface {
126126
// panic.
127127
IsSuperset(other Set) bool
128128

129+
// Iterates over elements and executes the passed func against each element.
130+
// If passed func returns true, stop iteration at the time.
131+
Each(func(interface{}) bool)
132+
129133
// Returns a channel of elements that you can
130134
// range over.
131135
Iter() <-chan interface{}

set_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,37 @@ func Test_UnsafeSetClone(t *testing.T) {
849849
}
850850
}
851851

852+
func Test_Each(t *testing.T) {
853+
a := NewSet()
854+
855+
a.Add("Z")
856+
a.Add("Y")
857+
a.Add("X")
858+
a.Add("W")
859+
860+
b := NewSet()
861+
a.Each(func(elem interface{}) bool {
862+
b.Add(elem)
863+
return false
864+
})
865+
866+
if !a.Equal(b) {
867+
t.Error("The sets are not equal after iterating (Each) through the first set")
868+
}
869+
870+
var count int
871+
a.Each(func(elem interface{}) bool {
872+
if count == 2 {
873+
return true
874+
}
875+
count++
876+
return false
877+
})
878+
if count != 2 {
879+
t.Error("Iteration should stop on the way")
880+
}
881+
}
882+
852883
func Test_Iter(t *testing.T) {
853884
a := NewSet()
854885

threadsafe.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,16 @@ func (set *threadSafeSet) Cardinality() int {
151151
return len(set.s)
152152
}
153153

154+
func (set *threadSafeSet) Each(cb func(interface{}) bool) {
155+
set.RLock()
156+
for elem := range set.s {
157+
if cb(elem) {
158+
break
159+
}
160+
}
161+
set.RUnlock()
162+
}
163+
154164
func (set *threadSafeSet) Iter() <-chan interface{} {
155165
ch := make(chan interface{})
156166
go func() {

threadsafe_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"math/rand"
3131
"runtime"
3232
"sync"
33+
"sync/atomic"
3334
"testing"
3435
)
3536

@@ -294,6 +295,35 @@ func Test_IsProperSupersetConcurrent(t *testing.T) {
294295
wg.Wait()
295296
}
296297

298+
func Test_EachConcurrent(t *testing.T) {
299+
runtime.GOMAXPROCS(2)
300+
concurrent := 10
301+
302+
s := NewSet()
303+
ints := rand.Perm(N)
304+
for _, v := range ints {
305+
s.Add(v)
306+
}
307+
308+
var count int64
309+
wg := new(sync.WaitGroup)
310+
wg.Add(concurrent)
311+
for n := 0; n < concurrent; n++ {
312+
go func() {
313+
defer wg.Done()
314+
s.Each(func(elem interface{}) bool {
315+
atomic.AddInt64(&count, 1)
316+
return false
317+
})
318+
}()
319+
}
320+
wg.Wait()
321+
322+
if count != int64(N*concurrent) {
323+
t.Errorf("%v != %v", count, int64(N*concurrent))
324+
}
325+
}
326+
297327
func Test_IterConcurrent(t *testing.T) {
298328
runtime.GOMAXPROCS(2)
299329

threadunsafe.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ func (set *threadUnsafeSet) Cardinality() int {
159159
return len(*set)
160160
}
161161

162+
func (set *threadUnsafeSet) Each(cb func(interface{}) bool) {
163+
for elem := range *set {
164+
if cb(elem) {
165+
break
166+
}
167+
}
168+
}
169+
162170
func (set *threadUnsafeSet) Iter() <-chan interface{} {
163171
ch := make(chan interface{})
164172
go func() {

0 commit comments

Comments
 (0)