github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/cmd/go/internal/par/work.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 // Package par implements parallel execution helpers. 6 package par 7 8 import ( 9 "github.com/shogo82148/std/errors" 10 "github.com/shogo82148/std/sync" 11 ) 12 13 // Work manages a set of work items to be executed in parallel, at most once each. 14 // The items in the set must all be valid map keys. 15 type Work[T comparable] struct { 16 f func(T) 17 running int 18 19 mu sync.Mutex 20 added map[T]bool 21 todo []T 22 wait sync.Cond 23 waiting int 24 } 25 26 // Add adds item to the work set, if it hasn't already been added. 27 func (w *Work[T]) Add(item T) 28 29 // Do runs f in parallel on items from the work set, 30 // with at most n invocations of f running at a time. 31 // It returns when everything added to the work set has been processed. 32 // At least one item should have been added to the work set 33 // before calling Do (or else Do returns immediately), 34 // but it is allowed for f(item) to add new items to the set. 35 // Do should only be used once on a given Work. 36 func (w *Work[T]) Do(n int, f func(item T)) 37 38 // ErrCache is like Cache except that it also stores 39 // an error value alongside the cached value V. 40 type ErrCache[K comparable, V any] struct { 41 Cache[K, errValue[V]] 42 } 43 44 func (c *ErrCache[K, V]) Do(key K, f func() (V, error)) (V, error) 45 46 var ErrCacheEntryNotFound = errors.New("cache entry not found") 47 48 // Get returns the cached result associated with key. 49 // It returns ErrCacheEntryNotFound if there is no such result. 50 func (c *ErrCache[K, V]) Get(key K) (V, error) 51 52 // Cache runs an action once per key and caches the result. 53 type Cache[K comparable, V any] struct { 54 m sync.Map 55 } 56 57 // Do calls the function f if and only if Do is being called for the first time with this key. 58 // No call to Do with a given key returns until the one call to f returns. 59 // Do returns the value returned by the one call to f. 60 func (c *Cache[K, V]) Do(key K, f func() V) V 61 62 // Get returns the cached result associated with key 63 // and reports whether there is such a result. 64 // 65 // If the result for key is being computed, Get does not wait for the computation to finish. 66 func (c *Cache[K, V]) Get(key K) (V, bool) 67 68 // Clear removes all entries in the cache. 69 // 70 // Concurrent calls to Get may return old values. Concurrent calls to Do 71 // may return old values or store results in entries that have been deleted. 72 // 73 // TODO(jayconrod): Delete this after the package cache clearing functions 74 // in internal/load have been removed. 75 func (c *Cache[K, V]) Clear() 76 77 // Delete removes an entry from the map. It is safe to call Delete for an 78 // entry that does not exist. Delete will return quickly, even if the result 79 // for a key is still being computed; the computation will finish, but the 80 // result won't be accessible through the cache. 81 // 82 // TODO(jayconrod): Delete this after the package cache clearing functions 83 // in internal/load have been removed. 84 func (c *Cache[K, V]) Delete(key K) 85 86 // DeleteIf calls pred for each key in the map. If pred returns true for a key, 87 // DeleteIf removes the corresponding entry. If the result for a key is 88 // still being computed, DeleteIf will remove the entry without waiting for 89 // the computation to finish. The result won't be accessible through the cache. 90 // 91 // TODO(jayconrod): Delete this after the package cache clearing functions 92 // in internal/load have been removed. 93 func (c *Cache[K, V]) DeleteIf(pred func(key K) bool)