Skip to content

Commit a658948

Browse files
committed
feat: separate mapreduce from go-zero
1 parent 0ade9e6 commit a658948

9 files changed

+1034
-0
lines changed

atomicerror.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package mapreduce
2+
3+
import "sync/atomic"
4+
5+
// AtomicError defines an atomic error.
6+
type AtomicError struct {
7+
err atomic.Value // error
8+
}
9+
10+
// Set sets the error.
11+
func (ae *AtomicError) Set(err error) {
12+
if err != nil {
13+
ae.err.Store(err)
14+
}
15+
}
16+
17+
// Load returns the error.
18+
func (ae *AtomicError) Load() error {
19+
if v := ae.err.Load(); v != nil {
20+
return v.(error)
21+
}
22+
return nil
23+
}

atomicerror_test.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package mapreduce
2+
3+
import (
4+
"errors"
5+
"sync"
6+
"sync/atomic"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
var errAtomicDummy = errors.New("hello")
13+
14+
func TestAtomicError(t *testing.T) {
15+
var err AtomicError
16+
err.Set(errAtomicDummy)
17+
assert.Equal(t, errAtomicDummy, err.Load())
18+
}
19+
20+
func TestAtomicErrorSetNil(t *testing.T) {
21+
var (
22+
errNil error
23+
err AtomicError
24+
)
25+
err.Set(errNil)
26+
assert.Equal(t, errNil, err.Load())
27+
}
28+
29+
func TestAtomicErrorNil(t *testing.T) {
30+
var err AtomicError
31+
assert.Nil(t, err.Load())
32+
}
33+
34+
func BenchmarkAtomicError(b *testing.B) {
35+
var aerr AtomicError
36+
wg := sync.WaitGroup{}
37+
38+
b.Run("Load", func(b *testing.B) {
39+
var done uint32
40+
go func() {
41+
for {
42+
if atomic.LoadUint32(&done) != 0 {
43+
break
44+
}
45+
wg.Add(1)
46+
go func() {
47+
aerr.Set(errAtomicDummy)
48+
wg.Done()
49+
}()
50+
}
51+
}()
52+
b.ResetTimer()
53+
for i := 0; i < b.N; i++ {
54+
_ = aerr.Load()
55+
}
56+
b.StopTimer()
57+
atomic.StoreUint32(&done, 1)
58+
wg.Wait()
59+
})
60+
b.Run("Set", func(b *testing.B) {
61+
var done uint32
62+
go func() {
63+
for {
64+
if atomic.LoadUint32(&done) != 0 {
65+
break
66+
}
67+
wg.Add(1)
68+
go func() {
69+
_ = aerr.Load()
70+
wg.Done()
71+
}()
72+
}
73+
}()
74+
b.ResetTimer()
75+
for i := 0; i < b.N; i++ {
76+
aerr.Set(errAtomicDummy)
77+
}
78+
b.StopTimer()
79+
atomic.StoreUint32(&done, 1)
80+
wg.Wait()
81+
})
82+
}

donechan.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package mapreduce
2+
3+
import "sync"
4+
5+
// A DoneChan is used as a channel that can be closed multiple times and wait for done.
6+
type DoneChan struct {
7+
done chan struct{}
8+
once sync.Once
9+
}
10+
11+
// NewDoneChan returns a DoneChan.
12+
func NewDoneChan() *DoneChan {
13+
return &DoneChan{
14+
done: make(chan struct{}),
15+
}
16+
}
17+
18+
// Close closes dc, it's safe to close more than once.
19+
func (dc *DoneChan) Close() {
20+
dc.once.Do(func() {
21+
close(dc.done)
22+
})
23+
}
24+
25+
// Done returns a channel that can be notified on dc closed.
26+
func (dc *DoneChan) Done() chan struct{} {
27+
return dc.done
28+
}

donechan_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package mapreduce
2+
3+
import (
4+
"sync"
5+
"testing"
6+
)
7+
8+
func TestDoneChanClose(t *testing.T) {
9+
doneChan := NewDoneChan()
10+
11+
for i := 0; i < 5; i++ {
12+
doneChan.Close()
13+
}
14+
}
15+
16+
func TestDoneChanDone(t *testing.T) {
17+
var waitGroup sync.WaitGroup
18+
doneChan := NewDoneChan()
19+
20+
waitGroup.Add(1)
21+
go func() {
22+
<-doneChan.Done()
23+
waitGroup.Done()
24+
}()
25+
26+
for i := 0; i < 5; i++ {
27+
doneChan.Close()
28+
}
29+
30+
waitGroup.Wait()
31+
}

go.mod

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module github.com/kevwan/mapreduce
2+
3+
go 1.14
4+
5+
require github.com/stretchr/testify v1.7.0
6+
7+
require (
8+
github.com/davecgh/go-spew v1.1.1 // indirect
9+
github.com/kr/text v0.2.0 // indirect
10+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
11+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
12+
)

go.sum

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
6+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
7+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
8+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
9+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
10+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
11+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
12+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
13+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
14+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
15+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
17+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
18+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
19+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
20+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
21+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)