Skip to content

Commit

Permalink
Use fillmore-labs.com/lazydone
Browse files Browse the repository at this point in the history
Signed-off-by: Oliver Eikemeier <eikemeier@fillmore-labs.com>
  • Loading branch information
eikemeier committed Apr 29, 2024
1 parent 356bf47 commit 187bb58
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 129 deletions.
1 change: 0 additions & 1 deletion .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ exclude_patterns:
- "**/.*"
- "**/*_test.go"
- "**/*.md"
- "**/nocopy.go"
- "LICENSE"
- "go.mod"
- "go.sum"
Expand Down
2 changes: 0 additions & 2 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@ coverage:
status:
project: false
patch: false
ignore:
- "nocopy.go"
5 changes: 4 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ linters:
- depguard
- exhaustruct
- forbidigo
- ireturn
- nonamedreturns
- varnamelen
- wrapcheck
Expand All @@ -32,3 +31,7 @@ linters-settings:
enable-all: true
disable:
- require-error
ireturn:
allow:
- error
- generic
24 changes: 0 additions & 24 deletions closedchan.go

This file was deleted.

38 changes: 8 additions & 30 deletions future.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"fmt"
)

// ErrNotReady is returned when a future is not complete.
// ErrNotReady is returned when the future is not complete.
var ErrNotReady = errors.New("future not ready")

// Future represents a read-only view of the result of an asynchronous operation.
Expand Down Expand Up @@ -52,18 +52,11 @@ func (f *Future[R]) Await(ctx context.Context) (R, error) {

// Try returns the cached result when ready, [ErrNotReady] otherwise.
func (f *Future[R]) Try() (R, error) {
if f != nil {
if done := f.done.Load(); done != nil {
select {
case <-*done:
return f.value, f.err

default:
}
}
if f == nil || !f.done.Closed() {
return *new(R), ErrNotReady
}

return *new(R), ErrNotReady
return f.value, f.err
}

// Done returns a channel that is closed when the future is complete.
Expand All @@ -73,32 +66,17 @@ func (f *Future[_]) Done() <-chan struct{} {
return nil
}

if done := f.done.Load(); done != nil {
return *done
}

done := make(chan struct{})
if f.done.CompareAndSwap(nil, &done) {
return done
}

done2 := f.done.Load()

return *done2
return f.done.Done()
}

func (f *Future[R]) String() string {
if f == nil {
return "Future <nil>"
}

if done := f.done.Load(); done != nil {
select {
case <-*done:
return fmt.Sprintf("Future resolved: %v, %v", f.value, f.err)
default:
}
if !f.done.Closed() {
return "Future pending"
}

return "Future pending"
return fmt.Sprintf("Future resolved: %v, %v", f.value, f.err)
}
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ module fillmore-labs.com/async

go 1.21

toolchain go1.22.1
toolchain go1.22.2

require (
fillmore-labs.com/lazydone v0.0.2
github.com/stretchr/testify v1.9.0
go.uber.org/goleak v1.3.0
golang.org/x/sync v0.7.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sync v0.6.0
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
20 changes: 8 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
fillmore-labs.com/lazydone v0.0.2 h1:y6LZlS32691K2T3mvmbYJ7qnwOTQgWG6NeG6E023EOI=
fillmore-labs.com/lazydone v0.0.2/go.mod h1:/v+72piFl79m/Ik8noCymbQmxWD/WtJm5FCeafWdkD0=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
26 changes: 14 additions & 12 deletions group/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type Option interface {
}

// WithLimit is an [Option] to configure the limit of active goroutines.
func WithLimit(limit int) Option {
func WithLimit(limit int) Option { //nolint:ireturn
if limit < 1 {
panic("limit must be at least 1")
}
Expand All @@ -83,7 +83,7 @@ func (o limitOption) apply(opts *options) {
// WithCancel is an [Option] to cancel a context on the first error.
//
// cancel is a function retrieved from [context.WithCancelCause].
func WithCancel(cancel context.CancelCauseFunc) Option {
func WithCancel(cancel context.CancelCauseFunc) Option { //nolint:ireturn
return cancelOption{cancel: cancel}
}

Expand Down Expand Up @@ -135,20 +135,22 @@ func DoAsync[R any](ctx context.Context, g *Group, fn func() (R, error)) *async.
return p.Future()
}

go p.Do(func() (R, error) {
go func() {
defer g.release()

value, err := func() (value R, err error) {
defer g.recover(&err)
p.Do(func() (R, error) {
value, err := func() (value R, err error) {
defer g.recover(&err)

return fn()
}()
if err != nil {
g.setError(err)
}
return fn()
}()
if err != nil {
g.setError(err)
}

return value, err
})
return value, err
})
}()

return p.Future()
}
Expand Down
22 changes: 0 additions & 22 deletions nocopy.go

This file was deleted.

32 changes: 11 additions & 21 deletions promise.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ package async

import (
"fmt"
"sync/atomic"

"fillmore-labs.com/lazydone"
)

// Promise defines the common operations for resolving a [Future] to its final value.
//
// An empty value is valid and must not be copied after creation. One of the resolving
// operations may be called once from any goroutine, all subsequent calls will panic.
type Promise[R any] struct {
_ noCopy
done atomic.Pointer[chan struct{}] // lazy chan, signals when future has completed
value R // result value, protected by done
err error // result error, protected by done
done lazydone.Lazy // lazy chan, signals when future has completed
value R // result value, protected by done
err error // result error, protected by done
}

// Future returns a [Future] for this promise.
Expand All @@ -44,7 +44,7 @@ func (p *Promise[R]) Resolve(value R) {
}

p.value = value
p.close()
p.done.Close()
}

// Reject breaks the promise with an error.
Expand All @@ -54,7 +54,7 @@ func (p *Promise[R]) Reject(err error) {
}

p.err = err
p.close()
p.done.Close()
}

// Do runs fn synchronously, fulfilling the promise once it completes.
Expand All @@ -64,27 +64,17 @@ func (p *Promise[R]) Do(fn func() (R, error)) {
}

p.value, p.err = fn()
p.close()
}

func (p *Promise[R]) close() {
if done := p.done.Swap(&closedChan); done != nil {
close(*done)
}
p.done.Close()
}

func (p *Promise[R]) String() string {
if p == nil {
return "Promise <nil>"
}

if done := p.done.Load(); done != nil {
select {
case <-*done:
return fmt.Sprintf("Promise resolved: %v, %v", p.value, p.err)
default:
}
if !p.done.Closed() {
return "Promise pending"
}

return "Promise pending"
return fmt.Sprintf("Promise resolved: %v, %v", p.value, p.err)
}

0 comments on commit 187bb58

Please sign in to comment.