diff options
Diffstat (limited to 'packages/tui/internal/util')
| -rw-r--r-- | packages/tui/internal/util/concurrency.go | 50 | ||||
| -rw-r--r-- | packages/tui/internal/util/util.go | 10 |
2 files changed, 60 insertions, 0 deletions
diff --git a/packages/tui/internal/util/concurrency.go b/packages/tui/internal/util/concurrency.go new file mode 100644 index 000000000..fb6eecec8 --- /dev/null +++ b/packages/tui/internal/util/concurrency.go @@ -0,0 +1,50 @@ +package util + +import ( + "strings" + "sync" +) + +// MapReducePar performs a parallel map-reduce operation on a slice of items. +// It applies a function to each item in the slice concurrently, +// and combines the results serially using a reducer returned from +// each one of the functions, allowing the use of closures. +func MapReducePar[a, b any](items []a, init b, fn func(a) func(b) b) b { + itemCount := len(items) + locks := make([]*sync.Mutex, itemCount) + mapped := make([]func(b) b, itemCount) + + for i, value := range items { + lock := &sync.Mutex{} + lock.Lock() + locks[i] = lock + go func() { + defer lock.Unlock() + mapped[i] = fn(value) + }() + } + + result := init + for i := range itemCount { + locks[i].Lock() + defer locks[i].Unlock() + f := mapped[i] + if f != nil { + result = f(result) + } + } + + return result +} + +// WriteStringsPar allows to iterate over a list and compute strings in parallel, +// yet write them in order. +func WriteStringsPar[a any](sb *strings.Builder, items []a, fn func(a) string) { + MapReducePar(items, sb, func(item a) func(*strings.Builder) *strings.Builder { + str := fn(item) + return func(sbdr *strings.Builder) *strings.Builder { + sbdr.WriteString(str) + return sbdr + } + }) +} diff --git a/packages/tui/internal/util/util.go b/packages/tui/internal/util/util.go index c7fd98a8c..da12cc5b3 100644 --- a/packages/tui/internal/util/util.go +++ b/packages/tui/internal/util/util.go @@ -1,8 +1,10 @@ package util import ( + "log/slog" "os" "strings" + "time" tea "github.com/charmbracelet/bubbletea/v2" ) @@ -35,3 +37,11 @@ func IsWsl() bool { return false } + +func Measure(tag string) func(...any) { + startTime := time.Now() + return func(tags ...any) { + args := append([]any{"timeTakenMs", time.Since(startTime).Milliseconds()}, tags...) + slog.Info(tag, args...) + } +} |
