summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6/future.go
diff options
context:
space:
mode:
authorMikoĊ‚aj Walczak <mikiwalczak+github@gmail.com>2018-07-12 10:51:38 +0100
committerinsomniac <insomniacslk@users.noreply.github.com>2018-07-12 10:51:38 +0100
commit8e3bcdab237624421034ccc4eb16f260d4338aec (patch)
tree0cb93b736c59506f68df67ac1150e80047dc202c /dhcpv6/future.go
parent34154e71da6f5b4527809dc0babdefcbd262281c (diff)
Asynchronous client for DHCPv6 (#80)
Diffstat (limited to 'dhcpv6/future.go')
-rw-r--r--dhcpv6/future.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/dhcpv6/future.go b/dhcpv6/future.go
new file mode 100644
index 0000000..b431419
--- /dev/null
+++ b/dhcpv6/future.go
@@ -0,0 +1,111 @@
+package dhcpv6
+
+import (
+ "errors"
+ "time"
+)
+
+// Response represents a value which Future resolves to
+type Response interface {
+ Value() DHCPv6
+ Error() error
+}
+
+// Future is a result of an asynchronous DHCPv6 call
+type Future (<-chan Response)
+
+// SuccessFun can be used as a success callback
+type SuccessFun func(val DHCPv6) Future
+
+// FailureFun can be used as a failure callback
+type FailureFun func(err error) Future
+
+type response struct {
+ val DHCPv6
+ err error
+}
+
+func (r *response) Value() DHCPv6 {
+ return r.val
+}
+
+func (r *response) Error() error {
+ return r.err
+}
+
+// NewFuture creates a new future, which can be written to
+func NewFuture() chan Response {
+ return make(chan Response)
+}
+
+// NewResponse creates a new future response
+func NewResponse(val DHCPv6, err error) Response {
+ return &response{val: val, err: err}
+}
+
+// NewSuccessFuture creates a future that resolves to a value
+func NewSuccessFuture(val DHCPv6) Future {
+ f := NewFuture()
+ go func() {
+ f <- NewResponse(val, nil)
+ }()
+ return f
+}
+
+// NewFailureFuture creates a future that resolves to an error
+func NewFailureFuture(err error) Future {
+ f := NewFuture()
+ go func() {
+ f <- NewResponse(nil, err)
+ }()
+ return f
+}
+
+// Then allows to chain the futures executing appropriate function depending
+// on the previous future value
+func (f Future) Then(success SuccessFun, failure FailureFun) Future {
+ g := NewFuture()
+ go func() {
+ r := <-f
+ if r.Error() != nil {
+ r = <-failure(r.Error())
+ g <- r
+ } else {
+ r = <-success(r.Value())
+ g <- r
+ }
+ }()
+ return g
+}
+
+// OnSuccess allows to chain the futures executing next one only if the first
+// one succeeds
+func (f Future) OnSuccess(success SuccessFun) Future {
+ return f.Then(success, func(err error) Future {
+ return NewFailureFuture(err)
+ })
+}
+
+// OnFailure allows to chain the futures executing next one only if the first
+// one fails
+func (f Future) OnFailure(failure FailureFun) Future {
+ return f.Then(func(val DHCPv6) Future {
+ return NewSuccessFuture(val)
+ }, failure)
+}
+
+// Wait blocks the execution until a future resolves
+func (f Future) Wait() (DHCPv6, error) {
+ r := <-f
+ return r.Value(), r.Error()
+}
+
+// WaitTimeout blocks the execution until a future resolves or times out
+func (f Future) WaitTimeout(timeout time.Duration) (DHCPv6, error) {
+ select {
+ case r := <-f:
+ return r.Value(), r.Error()
+ case <-time.After(timeout):
+ return nil, errors.New("Timed out")
+ }
+}