github.com/bir3/gocompiler@v0.9.2202/src/xvendor/golang.org/x/mod/sumdb/cache.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Parallel cache. 6 // This file is copied from cmd/go/internal/par. 7 8 package sumdb 9 10 import ( 11 "sync" 12 "sync/atomic" 13 ) 14 15 // parCache runs an action once per key and caches the result. 16 type parCache struct { 17 m sync.Map 18 } 19 20 type cacheEntry struct { 21 done uint32 22 mu sync.Mutex 23 result interface{} 24 } 25 26 // Do calls the function f if and only if Do is being called for the first time with this key. 27 // No call to Do with a given key returns until the one call to f returns. 28 // Do returns the value returned by the one call to f. 29 func (c *parCache) Do(key interface{}, f func() interface{}) interface{} { 30 entryIface, ok := c.m.Load(key) 31 if !ok { 32 entryIface, _ = c.m.LoadOrStore(key, new(cacheEntry)) 33 } 34 e := entryIface.(*cacheEntry) 35 if atomic.LoadUint32(&e.done) == 0 { 36 e.mu.Lock() 37 if atomic.LoadUint32(&e.done) == 0 { 38 e.result = f() 39 atomic.StoreUint32(&e.done, 1) 40 } 41 e.mu.Unlock() 42 } 43 return e.result 44 } 45 46 // Get returns the cached result associated with key. 47 // It returns nil if there is no such result. 48 // If the result for key is being computed, Get does not wait for the computation to finish. 49 func (c *parCache) Get(key interface{}) interface{} { 50 entryIface, ok := c.m.Load(key) 51 if !ok { 52 return nil 53 } 54 e := entryIface.(*cacheEntry) 55 if atomic.LoadUint32(&e.done) == 0 { 56 return nil 57 } 58 return e.result 59 }