Skip to content

Commit

Permalink
refactor: use atomic.Int32 type (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
reugn authored Oct 29, 2023
1 parent ab0c12e commit d402489
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 20 deletions.
8 changes: 4 additions & 4 deletions once_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ func TestOnce(t *testing.T) {

func TestOnceConcurrent(t *testing.T) {
var once Once[int32]
var count int32
var count atomic.Int32
var wg sync.WaitGroup

for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
result, _ := once.Do(func() (int32, error) {
newCount := atomic.AddInt32(&count, 1)
newCount := count.Add(1)
return newCount, nil
})
atomic.StoreInt32(&count, result)
count.Store(result)
}()
}
wg.Wait()
assert.Equal(t, count, 1)
assert.Equal(t, int(count.Load()), 1)
}

func TestOncePanic(t *testing.T) {
Expand Down
10 changes: 5 additions & 5 deletions wait_group_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
type WaitGroupContext struct {
ctx context.Context
done chan struct{}
counter int32
state int32
counter atomic.Int32
state atomic.Int32
}

// NewWaitGroupContext returns a new WaitGroupContext with Context ctx.
Expand All @@ -29,10 +29,10 @@ func NewWaitGroupContext(ctx context.Context) *WaitGroupContext {
// If the counter becomes zero, all goroutines blocked on Wait are released.
// If the counter goes negative, Add panics.
func (wgc *WaitGroupContext) Add(delta int) {
counter := atomic.AddInt32(&wgc.counter, int32(delta))
if counter == 0 && atomic.CompareAndSwapInt32(&wgc.state, 0, 1) {
counter := wgc.counter.Add(int32(delta))
if counter == 0 && wgc.state.CompareAndSwap(0, 1) {
wgc.release()
} else if counter < 0 && atomic.LoadInt32(&wgc.state) == 0 {
} else if counter < 0 && wgc.state.Load() == 0 {
panic("async: negative WaitGroupContext counter")
}
}
Expand Down
23 changes: 12 additions & 11 deletions wait_group_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,45 @@ package async

import (
"context"
"sync/atomic"
"testing"
"time"

"github.com/reugn/async/internal/assert"
)

func TestWaitGroupContext(t *testing.T) {
result := 0
var result atomic.Int32
wgc := NewWaitGroupContext(context.Background())
wgc.Add(2)

go func() {
defer wgc.Done()
time.Sleep(time.Millisecond * 10)
result++
result.Add(1)
}()
go func() {
defer wgc.Done()
time.Sleep(time.Millisecond * 20)
result += 2
result.Add(2)
}()
go func() {
wgc.Wait()
result += 3
result.Add(3)
}()

wgc.Wait()
time.Sleep(time.Millisecond * 10)

assert.Equal(t, result, 6)
assert.Equal(t, int(result.Load()), 6)
}

func TestWaitGroupContextCanceled(t *testing.T) {
result := 0
var result atomic.Int32
ctx, cancelFunc := context.WithCancel(context.Background())
go func() {
time.Sleep(time.Millisecond * 100)
result += 10
result.Add(10)
cancelFunc()
}()
wgc := NewWaitGroupContext(ctx)
Expand All @@ -48,22 +49,22 @@ func TestWaitGroupContextCanceled(t *testing.T) {
go func() {
defer wgc.Done()
time.Sleep(time.Millisecond * 10)
result++
result.Add(1)
}()
go func() {
defer wgc.Done()
time.Sleep(time.Millisecond * 300)
result += 2
result.Add(2)
}()
go func() {
wgc.Wait()
result += 100
result.Add(100)
}()

wgc.Wait()
time.Sleep(time.Millisecond * 10)

assert.Equal(t, result, 111)
assert.Equal(t, int(result.Load()), 111)
}

func TestWaitGroupContextPanic(t *testing.T) {
Expand Down

0 comments on commit d402489

Please sign in to comment.