summaryrefslogtreecommitdiff
path: root/src/mongo/gotools/vendor/src/github.com/spacemonkeygo/openssl/utils/future.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/gotools/vendor/src/github.com/spacemonkeygo/openssl/utils/future.go')
-rw-r--r--src/mongo/gotools/vendor/src/github.com/spacemonkeygo/openssl/utils/future.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/mongo/gotools/vendor/src/github.com/spacemonkeygo/openssl/utils/future.go b/src/mongo/gotools/vendor/src/github.com/spacemonkeygo/openssl/utils/future.go
new file mode 100644
index 00000000000..fa1bbbfb861
--- /dev/null
+++ b/src/mongo/gotools/vendor/src/github.com/spacemonkeygo/openssl/utils/future.go
@@ -0,0 +1,79 @@
+// Copyright (C) 2014 Space Monkey, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+ "sync"
+)
+
+// Future is a type that is essentially the inverse of a channel. With a
+// channel, you have multiple senders and one receiver. With a future, you can
+// have multiple receivers and one sender. Additionally, a future protects
+// against double-sends. Since this is usually used for returning function
+// results, we also capture and return error values as well. Use NewFuture
+// to initialize.
+type Future struct {
+ mutex *sync.Mutex
+ cond *sync.Cond
+ received bool
+ val interface{}
+ err error
+}
+
+// NewFuture returns an initialized and ready Future.
+func NewFuture() *Future {
+ mutex := &sync.Mutex{}
+ return &Future{
+ mutex: mutex,
+ cond: sync.NewCond(mutex),
+ received: false,
+ val: nil,
+ err: nil,
+ }
+}
+
+// Get blocks until the Future has a value set.
+func (self *Future) Get() (interface{}, error) {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+ for {
+ if self.received {
+ return self.val, self.err
+ }
+ self.cond.Wait()
+ }
+}
+
+// Fired returns whether or not a value has been set. If Fired is true, Get
+// won't block.
+func (self *Future) Fired() bool {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+ return self.received
+}
+
+// Set provides the value to present and future Get calls. If Set has already
+// been called, this is a no-op.
+func (self *Future) Set(val interface{}, err error) {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+ if self.received {
+ return
+ }
+ self.received = true
+ self.val = val
+ self.err = err
+ self.cond.Broadcast()
+}