commit:     eb788da3f1af8f506226986f12de6b2b04cdaba1
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Sun Jun  2 03:42:00 2024 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Wed Jun 12 07:06:42 2024 +0000
URL:        
https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=eb788da3

Add the parallel_run() function

Here is an example of how to use it.

$ parallel_run 0 sha256sum dir/*

Simple commands of a greater level of sophistication can easily be
composed with the aid of functions.

$ sm3sum() { cksum -a sm3 "$@"; }
$ parallel_run 0 sm3sum dir/*

Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>

 functions.sh   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 test-functions | 21 ++++++++++++++++++++-
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/functions.sh b/functions.sh
index 60a4b2e..e849541 100644
--- a/functions.sh
+++ b/functions.sh
@@ -495,6 +495,50 @@ oldest()
        _select_by_mtime -- "$@"
 }
 
+#
+# Executes a simple command in parallel. At least two parameters are expected.
+# The first parameter shall be taken as the maximum number of jobs to run
+# concurrently. If specified as less than or equal to 0, the number shall be
+# determined by running the nproc function. The second parameter shall be taken
+# as a command name. The remaining parameters shall be conveyed to the 
specified
+# command, one at a time. Should at least one command fail, the return value
+# shall be greater than 0.
+#
+parallel_run()
+{
+       local arg cmd i statedir w workers
+
+       if [ "$#" -lt 3 ]; then
+               warn "parallel_run: too few arguments (got $#, expected at 
least 3)"
+               return 1
+       elif ! is_int "$1"; then
+               _warn_for_args parallel_run "$1"
+               return 1
+       elif [ "$1" -le 0 ] && ! workers=$(get_nprocs); then
+               return 1
+       elif ! statedir=${TMPDIR:-/tmp}/parallel_run.$$.$(srandom); then
+               return 1
+       fi
+       workers=${workers:-$1} cmd=$2
+       shift 2
+       w=0
+       i=0
+       (
+               while [ "$(( w += 1 ))" -le "${workers}" ]; do
+                       i=$w
+                       while [ "$i" -le "$#" ]; do
+                               eval "arg=\$${i}"
+                               if ! "${cmd}" "${arg}"; then
+                                       mkdir -p -- "${statedir}"
+                               fi
+                               i=$(( i + workers ))
+                       done &
+               done
+               wait
+       )
+       ! rmdir -- "${statedir}" 2>/dev/null
+}
+
 #
 # Declare the vebegin, veerror, veindent, veinfo, veinfon, veoutdent and vewarn
 # functions. These differ from their non-v-prefixed counterparts in that they

diff --git a/test-functions b/test-functions
index c734141..ed3da42 100755
--- a/test-functions
+++ b/test-functions
@@ -556,6 +556,25 @@ test_get_nprocs() {
        iterate_tests 2 "$@"
 }
 
+test_parallel_run() {
+       set -- \
+               ge  1  N/A                     N/A                     \
+               eq  0  /                       N/A                     \
+               ge  1  /var/empty/nonexistent  N/A                     \
+               eq  0  /                       /                       \
+               ge  1  /                       /var/empty/nonexistent  \
+               ge  1  /var/empty/nonexistent  /var/empty/nonexistent  \
+               ge  1  /var/empty/nonexistent  /
+
+       callback() {
+               shift
+               test_description="parallel_run $(_print_args 0 ls "$@")"
+               parallel_run 0 ls "$@" >/dev/null 2>&1
+       }
+
+       iterate_tests 4 "$@"
+}
+
 iterate_tests() {
        slice_width=$1
        shift
@@ -621,7 +640,7 @@ test_newest || rc=1
 test_trim || rc=1
 test_hr || rc=1
 test_whenceforth || rc=1
-test_get_nprocs || rc=1
+test_parallel_run || rc=1
 
 cleanup_tmpdir
 

Reply via email to