diff options
| author | 2024-01-17 14:54:30 +0000 | |
|---|---|---|
| committer | 2024-01-17 14:54:30 +0000 | |
| commit | 906639ad7eb92e9d631599f78979908930e59c84 (patch) | |
| tree | dfef6d0a5ba47c49c214e4537a89dee6ad528df8 /vendor/github.com/sourcegraph/conc/iter/iter.go | |
| parent | [bugfix] Better Postgres search case insensitivity (#2526) (diff) | |
| download | gotosocial-906639ad7eb92e9d631599f78979908930e59c84.tar.xz | |
[chore] update viper version (#2539)
* update viper version
* removes our last uses of the slice package
* fix tests
Diffstat (limited to 'vendor/github.com/sourcegraph/conc/iter/iter.go')
| -rw-r--r-- | vendor/github.com/sourcegraph/conc/iter/iter.go | 85 | 
1 files changed, 85 insertions, 0 deletions
diff --git a/vendor/github.com/sourcegraph/conc/iter/iter.go b/vendor/github.com/sourcegraph/conc/iter/iter.go new file mode 100644 index 000000000..124b4f940 --- /dev/null +++ b/vendor/github.com/sourcegraph/conc/iter/iter.go @@ -0,0 +1,85 @@ +package iter + +import ( +	"runtime" +	"sync/atomic" + +	"github.com/sourcegraph/conc" +) + +// defaultMaxGoroutines returns the default maximum number of +// goroutines to use within this package. +func defaultMaxGoroutines() int { return runtime.GOMAXPROCS(0) } + +// Iterator can be used to configure the behaviour of ForEach +// and ForEachIdx. The zero value is safe to use with reasonable +// defaults. +// +// Iterator is also safe for reuse and concurrent use. +type Iterator[T any] struct { +	// MaxGoroutines controls the maximum number of goroutines +	// to use on this Iterator's methods. +	// +	// If unset, MaxGoroutines defaults to runtime.GOMAXPROCS(0). +	MaxGoroutines int +} + +// ForEach executes f in parallel over each element in input. +// +// It is safe to mutate the input parameter, which makes it +// possible to map in place. +// +// ForEach always uses at most runtime.GOMAXPROCS goroutines. +// It takes roughly 2µs to start up the goroutines and adds +// an overhead of roughly 50ns per element of input. For +// a configurable goroutine limit, use a custom Iterator. +func ForEach[T any](input []T, f func(*T)) { Iterator[T]{}.ForEach(input, f) } + +// ForEach executes f in parallel over each element in input, +// using up to the Iterator's configured maximum number of +// goroutines. +// +// It is safe to mutate the input parameter, which makes it +// possible to map in place. +// +// It takes roughly 2µs to start up the goroutines and adds +// an overhead of roughly 50ns per element of input. +func (iter Iterator[T]) ForEach(input []T, f func(*T)) { +	iter.ForEachIdx(input, func(_ int, t *T) { +		f(t) +	}) +} + +// ForEachIdx is the same as ForEach except it also provides the +// index of the element to the callback. +func ForEachIdx[T any](input []T, f func(int, *T)) { Iterator[T]{}.ForEachIdx(input, f) } + +// ForEachIdx is the same as ForEach except it also provides the +// index of the element to the callback. +func (iter Iterator[T]) ForEachIdx(input []T, f func(int, *T)) { +	if iter.MaxGoroutines == 0 { +		// iter is a value receiver and is hence safe to mutate +		iter.MaxGoroutines = defaultMaxGoroutines() +	} + +	numInput := len(input) +	if iter.MaxGoroutines > numInput { +		// No more concurrent tasks than the number of input items. +		iter.MaxGoroutines = numInput +	} + +	var idx atomic.Int64 +	// Create the task outside the loop to avoid extra closure allocations. +	task := func() { +		i := int(idx.Add(1) - 1) +		for ; i < numInput; i = int(idx.Add(1) - 1) { +			f(i, &input[i]) +		} +	} + +	var wg conc.WaitGroup +	for i := 0; i < iter.MaxGoroutines; i++ { +		wg.Go(task) +	} +	wg.Wait() +}  | 
