aboutsummaryrefslogtreecommitdiff
path: root/promise.go
diff options
context:
space:
mode:
Diffstat (limited to 'promise.go')
-rw-r--r--promise.go45
1 files changed, 45 insertions, 0 deletions
diff --git a/promise.go b/promise.go
new file mode 100644
index 0000000..29bd703
--- /dev/null
+++ b/promise.go
@@ -0,0 +1,45 @@
+// SPDX-FileCopyrightText: © 2024 Grégoire Duchêne <gduchene@awhk.org>
+// SPDX-License-Identifier: ISC
+
+package core
+
+import (
+ "errors"
+ "sync/atomic"
+)
+
+var ErrPromiseFulfilled = errors.New("promise fulfilled already")
+
+type Promise[T any] struct {
+ value chan T
+ error chan error
+ closed int32
+
+ _ NoCopy
+}
+
+func NewPromise[T any]() *Promise[T] {
+ return &Promise[T]{value: make(chan T, 1), error: make(chan error, 1), closed: 0}
+}
+
+func (p *Promise[T]) Err() <-chan error { return p.error }
+
+func (p *Promise[T]) FailWith(err error) error {
+ if !atomic.CompareAndSwapInt32(&p.closed, 0, 1) {
+ return ErrPromiseFulfilled
+ }
+ p.error <- err
+ close(p.error)
+ return nil
+}
+
+func (p *Promise[T]) SucceedWith(value T) error {
+ if !atomic.CompareAndSwapInt32(&p.closed, 0, 1) {
+ return ErrPromiseFulfilled
+ }
+ p.value <- value
+ close(p.value)
+ return nil
+}
+
+func (p *Promise[T]) Value() <-chan T { return p.value }