]> diplodocus.org Git - flac-archive/commitdiff
Add Python implemention of Jobs package.
authorepg <>
Wed, 26 Jul 2006 21:29:07 +0000 (21:29 +0000)
committerepg <>
Wed, 26 Jul 2006 21:29:07 +0000 (21:29 +0000)
jobs.py [new file with mode: 0644]
jobtest.py [new file with mode: 0644]

diff --git a/jobs.py b/jobs.py
new file mode 100644 (file)
index 0000000..5ce62b9
--- /dev/null
+++ b/jobs.py
@@ -0,0 +1,58 @@
+import os, sys
+
+from errno import ECHILD, EINTR
+
+from org.diplodocus.util import nothing
+
+def newjob(f, jobs, debug):
+    if not debug:
+        pid = os.fork()
+
+    if debug or pid == 0:
+        sys.exit(f())
+
+    jobs.append(pid)
+
+    return pid
+
+def run(get_job, maxjobs=1, notify_start=nothing, notify_finish=nothing,
+        debug=False):
+    jobs = []
+
+    while True:
+        if len(jobs) < maxjobs:
+            while True:
+                job = get_job()
+                if job == None:
+                    break
+                pid = newjob(job, jobs, debug)
+                notify_start(pid, jobs)
+                if len(jobs) == maxjobs:
+                    break
+
+            # No jobs running and get-job returned undef; we're finished.
+            if len(jobs) == 0 and job == None:
+                return
+
+        # Now running as many jobs as we can, block waiting for one to die.
+        while True:
+            try:
+                (pid, status) = os.waitpid(-1, 0)
+            except EnvironmentError, error:
+                if error.errno != ECHILD and error.errno != EINTR:
+                    raise
+            if pid > 0:
+                break
+
+        # Handle the finished job, and see if others have finished.
+        while True:
+            jobs.remove(pid)
+            notify_finish(pid, status, jobs)
+            try:
+                (pid, status) = os.waitpid(-1, os.WNOHANG)
+            except EnvironmentError, error:
+                if error.errno != ECHILD and error.errno != EINTR:
+                    raise
+                break
+            if pid == 0:
+                break
diff --git a/jobtest.py b/jobtest.py
new file mode 100644 (file)
index 0000000..23034d2
--- /dev/null
@@ -0,0 +1,16 @@
+import os
+import sys
+import jobs
+
+work = range(17)
+
+def getjob():
+    try:
+        job = work.pop()
+    except IndexError:
+        return None
+    return lambda: sys.stdout.write('%d %d\n'  % (os.getpid(), job))
+
+jobs.run(get_job=getjob, maxjobs=8,
+         notify_start=lambda pid, jobs: sys.stdout.write('%d %d jobs\n' % (pid, len(jobs))),
+         notify_finish=lambda pid, status, jobs: sys.stdout.write('%d %d %d jobs\n' % (pid, status, len(jobs))))