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)