summaryrefslogtreecommitdiff
path: root/libgo/go/net/singleflight.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/singleflight.go')
-rw-r--r--libgo/go/net/singleflight.go109
1 files changed, 0 insertions, 109 deletions
diff --git a/libgo/go/net/singleflight.go b/libgo/go/net/singleflight.go
deleted file mode 100644
index bf599f0cc94..00000000000
--- a/libgo/go/net/singleflight.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package net
-
-import "sync"
-
-// call is an in-flight or completed singleflight.Do call
-type call struct {
- wg sync.WaitGroup
-
- // These fields are written once before the WaitGroup is done
- // and are only read after the WaitGroup is done.
- val interface{}
- err error
-
- // These fields are read and written with the singleflight
- // mutex held before the WaitGroup is done, and are read but
- // not written after the WaitGroup is done.
- dups int
- chans []chan<- singleflightResult
-}
-
-// singleflight represents a class of work and forms a namespace in
-// which units of work can be executed with duplicate suppression.
-type singleflight struct {
- mu sync.Mutex // protects m
- m map[string]*call // lazily initialized
-}
-
-// singleflightResult holds the results of Do, so they can be passed
-// on a channel.
-type singleflightResult struct {
- v interface{}
- err error
- shared bool
-}
-
-// Do executes and returns the results of the given function, making
-// sure that only one execution is in-flight for a given key at a
-// time. If a duplicate comes in, the duplicate caller waits for the
-// original to complete and receives the same results.
-// The return value shared indicates whether v was given to multiple callers.
-func (g *singleflight) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
- g.mu.Lock()
- if g.m == nil {
- g.m = make(map[string]*call)
- }
- if c, ok := g.m[key]; ok {
- c.dups++
- g.mu.Unlock()
- c.wg.Wait()
- return c.val, c.err, true
- }
- c := new(call)
- c.wg.Add(1)
- g.m[key] = c
- g.mu.Unlock()
-
- g.doCall(c, key, fn)
- return c.val, c.err, c.dups > 0
-}
-
-// DoChan is like Do but returns a channel that will receive the
-// results when they are ready.
-func (g *singleflight) DoChan(key string, fn func() (interface{}, error)) <-chan singleflightResult {
- ch := make(chan singleflightResult, 1)
- g.mu.Lock()
- if g.m == nil {
- g.m = make(map[string]*call)
- }
- if c, ok := g.m[key]; ok {
- c.dups++
- c.chans = append(c.chans, ch)
- g.mu.Unlock()
- return ch
- }
- c := &call{chans: []chan<- singleflightResult{ch}}
- c.wg.Add(1)
- g.m[key] = c
- g.mu.Unlock()
-
- go g.doCall(c, key, fn)
-
- return ch
-}
-
-// doCall handles the single call for a key.
-func (g *singleflight) doCall(c *call, key string, fn func() (interface{}, error)) {
- c.val, c.err = fn()
- c.wg.Done()
-
- g.mu.Lock()
- delete(g.m, key)
- for _, ch := range c.chans {
- ch <- singleflightResult{c.val, c.err, c.dups > 0}
- }
- g.mu.Unlock()
-}
-
-// Forget tells the singleflight to forget about a key. Future calls
-// to Do for this key will call the function rather than waiting for
-// an earlier call to complete.
-func (g *singleflight) Forget(key string) {
- g.mu.Lock()
- delete(g.m, key)
- g.mu.Unlock()
-}