2013-04-23 18:51:17 +02:00
|
|
|
from __future__ import absolute_import
|
2015-11-01 17:11:06 +01:00
|
|
|
from __future__ import print_function
|
2017-03-03 19:01:52 +01:00
|
|
|
from typing import Any, Dict, Generator, Iterable, Tuple
|
2013-04-23 18:51:17 +02:00
|
|
|
|
2012-09-14 17:05:19 +02:00
|
|
|
import os
|
|
|
|
import pty
|
|
|
|
import sys
|
|
|
|
import errno
|
|
|
|
|
|
|
|
def run_parallel(job, data, threads=6):
|
2016-01-25 23:42:16 +01:00
|
|
|
# type: (Any, Iterable[Any], int) -> Generator[Tuple[int, Any], None, None]
|
|
|
|
pids = {} # type: Dict[int, Any]
|
2012-09-14 17:05:19 +02:00
|
|
|
|
|
|
|
def wait_for_one():
|
2016-07-30 01:02:48 +02:00
|
|
|
# type: () -> Tuple[int, Any]
|
2012-09-14 17:05:19 +02:00
|
|
|
while True:
|
|
|
|
try:
|
|
|
|
(pid, status) = os.wait()
|
|
|
|
return status, pids.pop(pid)
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
for item in data:
|
|
|
|
pid = os.fork()
|
|
|
|
if pid == 0:
|
|
|
|
sys.stdin.close()
|
|
|
|
try:
|
|
|
|
os.close(pty.STDIN_FILENO)
|
2015-11-01 17:08:33 +01:00
|
|
|
except OSError as e:
|
2012-09-14 17:05:19 +02:00
|
|
|
if e.errno != errno.EBADF:
|
|
|
|
raise
|
2016-07-03 15:19:32 +02:00
|
|
|
sys.stdin = open("/dev/null", "r") # type: ignore # py2 and py3 stubs are not compatible
|
2012-09-14 17:05:19 +02:00
|
|
|
os._exit(job(item))
|
|
|
|
|
|
|
|
pids[pid] = item
|
|
|
|
threads = threads - 1
|
|
|
|
|
|
|
|
if threads == 0:
|
|
|
|
(status, item) = wait_for_one()
|
|
|
|
threads += 1
|
|
|
|
yield (status, item)
|
|
|
|
if status != 0:
|
|
|
|
# Stop if any error occurred
|
|
|
|
break
|
|
|
|
|
|
|
|
while True:
|
|
|
|
try:
|
|
|
|
(status, item) = wait_for_one()
|
|
|
|
yield (status, item)
|
2015-11-01 17:08:33 +01:00
|
|
|
except OSError as e:
|
2012-09-14 17:05:19 +02:00
|
|
|
if e.errno == errno.ECHILD:
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
raise
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
# run some unit tests
|
|
|
|
import time
|
|
|
|
jobs = [10, 19, 18, 6, 14, 12, 8, 2, 1, 13, 3, 17, 9, 11, 5, 16, 7, 15, 4]
|
|
|
|
expected_output = [6, 10, 12, 2, 1, 14, 8, 3, 18, 19, 5, 9, 13, 11, 4, 7, 17, 16, 15]
|
2016-11-29 07:22:02 +01:00
|
|
|
|
2012-09-14 17:05:19 +02:00
|
|
|
def wait_and_print(x):
|
2016-07-30 01:02:48 +02:00
|
|
|
# type: (int) -> int
|
2012-09-14 17:05:19 +02:00
|
|
|
time.sleep(x * 0.1)
|
|
|
|
return 0
|
|
|
|
|
|
|
|
output = []
|
|
|
|
for (status, job) in run_parallel(wait_and_print, jobs):
|
|
|
|
output.append(job)
|
|
|
|
if output == expected_output:
|
2015-11-01 17:11:06 +01:00
|
|
|
print("Successfully passed test!")
|
2012-09-14 17:05:19 +02:00
|
|
|
else:
|
2015-11-01 17:11:06 +01:00
|
|
|
print("Failed test!")
|
|
|
|
print(jobs)
|
|
|
|
print(expected_output)
|
|
|
|
print(output)
|