File tree 9 files changed +1034
-0
lines changed
9 files changed +1034
-0
lines changed Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change
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
+ )
Original file line number Diff line number Diff line change
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 =
You can’t perform that action at this time.
0 commit comments