github.com/blend/go-sdk@v1.20220411.3/async/future.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package async 9 10 import ( 11 "context" 12 "sync" 13 ) 14 15 // Await returns a new future. 16 func Await(ctx context.Context, action ContextAction) *Future { 17 f := &Future{ 18 action: action, 19 finished: make(chan error), 20 } 21 ctx, f.cancel = context.WithCancel(ctx) 22 go f.do(ctx) 23 return f 24 } 25 26 // Future is a deferred action. 27 type Future struct { 28 mu sync.Mutex 29 action ContextAction 30 cancel func() 31 finished chan error 32 } 33 34 // Cancel quits the future. 35 func (f *Future) Cancel() error { 36 f.mu.Lock() 37 defer f.mu.Unlock() 38 if f.cancel == nil { 39 return ErrCannotCancel 40 } 41 f.cancel() 42 err, ok := <-f.finished 43 if ok { 44 close(f.finished) 45 } 46 f.cancel = nil 47 return err 48 } 49 50 // Complete blocks on the future completing. 51 func (f *Future) Complete() error { 52 f.mu.Lock() 53 defer f.mu.Unlock() 54 err, ok := <-f.finished 55 if ok { 56 close(f.finished) 57 f.cancel = nil 58 } 59 return err 60 } 61 62 // Finished returns a channel that signals it is finished. 63 func (f *Future) Finished() <-chan error { 64 return f.finished 65 } 66 67 func (f *Future) do(ctx context.Context) { 68 f.finished <- f.action(ctx) 69 }