From f437c8d7e29a0df4fe77768085d697a72ac461c3 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 10 Aug 2016 13:41:33 +0200
Subject: [PATCH] background sub-process limiter

---
 bash_multithread.sh | 84 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)
 create mode 100755 bash_multithread.sh

diff --git a/bash_multithread.sh b/bash_multithread.sh
new file mode 100755
index 0000000000..6006b95b1c
--- /dev/null
+++ b/bash_multithread.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+
+# slightly modified implementation of sub-process limiter
+# by paxdiablo. See http://stackoverflow.com/a/1685440
+
+# bgxupdate - update active processes in a group.
+#   Works by transferring each process to new group
+#   if it is still active.
+# in:  bgxgrp - current group of processes.
+# out: bgxgrp - new group of processes.
+# out: bgxcount - number of processes in new group.
+
+bgxupdate() {
+    bgxoldgrp=${bgxgrp}
+    bgxgrp=""
+    ((bgxcount = 0))
+    bgxjobs=" $(jobs -pr | tr '\n' ' ')"
+    for bgxpid in ${bgxoldgrp} ; do
+        echo "${bgxjobs}" | grep " ${bgxpid} " >/dev/null 2>&1
+        if [[ $? -eq 0 ]] ; then
+            bgxgrp="${bgxgrp} ${bgxpid}"
+            ((bgxcount = bgxcount + 1))
+        fi
+    done
+}
+
+# bgxlimit - start a sub-process with a limit.
+#   Loops, calling bgxupdate until there is a free
+#   slot to run another sub-process. Then runs it
+#   an updates the process group.
+# in:  $1     - the limit on processes.
+# in:  $2+    - the command to run for new process.
+# in:  bgxgrp - the current group of processes.
+# out: bgxgrp - new group of processes
+
+bgxlimit() {
+    bgxmax=$1 ; shift
+    bgxupdate
+    while [[ ${bgxcount} -ge ${bgxmax} ]] ; do
+        sleep 0.1
+        bgxupdate
+    done
+    if [[ "$1" != "-" ]] ; then
+        "$@" &
+        bgxgrp="${bgxgrp} $!"
+    fi
+    # echo '[' ${bgxgrp} ']'
+}
+
+# bgxwait - wait for sub-processes to finish
+#   Loops calling bgxupdate until there is something
+#   in a process group
+
+bgxwait() {
+    bgxupdate
+    while [[ ${bgxcount} -ne 0 ]] ; do
+        oldcount=${bgxcount}
+        while [[ ${oldcount} -eq ${bgxcount} ]] ; do
+            sleep 0.1
+            bgxupdate
+        done
+        # echo '[' ${bgxgrp} ']'
+    done
+}
+
+bgxtest() {
+    callback() {
+        id=$1 ; shift
+        echo start $id $(date | awk '{print $4}') "$BASHPID"
+        sleep ${id}0
+        echo end $id $(date | awk '{print $4}') "$BASHPID"
+    }
+
+    # Test program, create group and run 6 sleeps with
+    #   limit of 3.
+
+    bgxgrp=""
+    for i in 1 2 3 4 5 6 ; do
+        bgxlimit 3 callback ${i}
+    done
+
+    # Wait until all others are finished.
+    bgxwait;
+}
-- 
GitLab