Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(155)

Unified Diff: utils/voyeur/value.go

Issue 66000043: utils/voyeur: zero Value is ok to use
Patch Set: utils/voyeur: zero Value is ok to use Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « [revision details] ('k') | utils/voyeur/value_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/voyeur/value.go
=== modified file 'utils/voyeur/value.go'
--- utils/voyeur/value.go 2014-02-13 17:26:35 +0000
+++ utils/voyeur/value.go 2014-02-19 13:25:04 +0000
@@ -10,7 +10,9 @@
)
// Value represents a shared value that can be watched for changes. Methods on
-// a Value may be called concurrently.
+// a Value may be called concurrently. The zero Value is
+// ok to use, and is equivalent to a NewValue result
+// with a nil initial value.
type Value struct {
val interface{}
version int
@@ -23,7 +25,7 @@
// nil, any watchers will wait until a value is set.
func NewValue(initial interface{}) *Value {
v := new(Value)
- v.wait.L = v.mu.RLocker()
+ v.init()
if initial != nil {
v.val = initial
v.version++
@@ -31,19 +33,31 @@
return v
}
+func (v *Value) needsInit() bool {
+ return v.wait.L == nil
+}
+
+func (v *Value) init() {
+ if v.needsInit() {
+ v.wait.L = v.mu.RLocker()
+ }
+}
+
// Set sets the shared value to val.
func (v *Value) Set(val interface{}) {
v.mu.Lock()
+ v.init()
v.val = val
v.version++
+ v.mu.Unlock()
v.wait.Broadcast()
- v.mu.Unlock()
}
// Close closes the Value, unblocking any outstanding watchers. Close always
// returns nil.
func (v *Value) Close() error {
v.mu.Lock()
+ v.init()
v.closed = true
v.mu.Unlock()
v.wait.Broadcast()
@@ -79,8 +93,16 @@
// closed. Next returns false if the value or the Watcher itself have been
// closed.
func (w *Watcher) Next() bool {
- w.value.mu.RLock()
- defer w.value.mu.RUnlock()
+ val := w.value
+ val.mu.RLock()
+ defer val.mu.RUnlock()
+ if val.needsInit() {
+ val.mu.RUnlock()
+ val.mu.Lock()
+ val.init()
+ val.mu.Unlock()
+ val.mu.RLock()
+ }
// We can go around this loop a maximum of two times,
// because the only thing that can cause a Wait to
@@ -90,18 +112,18 @@
// causing the closed flag to be set.
// Both these cases will cause Next to return.
for {
- if w.version != w.value.version {
- w.version = w.value.version
- w.current = w.value.val
+ if w.version != val.version {
+ w.version = val.version
+ w.current = val.val
return true
}
- if w.value.closed || w.closed {
+ if val.closed || w.closed {
return false
}
// Wait releases the lock until triggered and then reacquires the lock,
// thus avoiding a deadlock.
- w.value.wait.Wait()
+ val.wait.Wait()
}
}
@@ -109,6 +131,7 @@
// value. It may be called concurrently with Next.
func (w *Watcher) Close() {
w.value.mu.Lock()
+ w.value.init()
w.closed = true
w.value.mu.Unlock()
w.value.wait.Broadcast()
« no previous file with comments | « [revision details] ('k') | utils/voyeur/value_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b