execProcesses optimization.

This commit is contained in:
cheatfate 2017-12-12 20:00:14 +02:00
commit 0429f41e98

View file

@ -257,6 +257,7 @@ proc execProcesses*(cmds: openArray[string],
var ecount = len(cmds) var ecount = len(cmds)
while ecount > 0: while ecount > 0:
var rexit = -1
when defined(windows): when defined(windows):
# waiting for all children, get result if any child exits # waiting for all children, get result if any child exits
var ret = waitForMultipleObjects(int32(wcount), addr(w), 0'i32, var ret = waitForMultipleObjects(int32(wcount), addr(w), 0'i32,
@ -273,6 +274,7 @@ proc execProcesses*(cmds: openArray[string],
discard getExitCodeProcess(q[r].fProcessHandle, status) discard getExitCodeProcess(q[r].fProcessHandle, status)
q[r].exitFlag = true q[r].exitFlag = true
q[r].exitStatus = status q[r].exitStatus = status
rexit = r
break break
else: else:
var status: cint = 1 var status: cint = 1
@ -281,16 +283,21 @@ proc execProcesses*(cmds: openArray[string],
if res > 0: if res > 0:
for r in 0..m-1: for r in 0..m-1:
if not isNil(q[r]) and q[r].id == res: if not isNil(q[r]) and q[r].id == res:
# we updating `exitStatus` manually, so `running()` can work.
if WIFEXITED(status) or WIFSIGNALED(status): if WIFEXITED(status) or WIFSIGNALED(status):
q[r].exitFlag = true q[r].exitFlag = true
q[r].exitStatus = status q[r].exitStatus = status
rexit = r
break break
else: else:
let err = osLastError() let err = osLastError()
if err == OSErrorCode(ECHILD): if err == OSErrorCode(ECHILD):
# some child exits, we need to check our childs exit codes # some child exits, we need to check our childs exit codes
discard for r in 0..m-1:
if (not isNil(q[r])) and (not running(q[r])):
q[r].exitFlag = true
q[r].exitStatus = status
rexit = r
break
elif err == OSErrorCode(EINTR): elif err == OSErrorCode(EINTR):
# signal interrupted our syscall, lets repeat it # signal interrupted our syscall, lets repeat it
continue continue
@ -298,29 +305,27 @@ proc execProcesses*(cmds: openArray[string],
# all other errors are exceptions # all other errors are exceptions
raiseOSError(err) raiseOSError(err)
for r in 0..m-1: if rexit >= 0:
if not isNil(q[r]): result = max(result, q[rexit].peekExitCode())
if not running(q[r]): if afterRunEvent != nil: afterRunEvent(rexit, q[rexit])
result = max(result, q[r].peekExitCode()) close(q[rexit])
if afterRunEvent != nil: afterRunEvent(r, q[r]) if i < len(cmds):
close(q[r]) if beforeRunEvent != nil: beforeRunEvent(i)
if i < len(cmds): q[rexit] = startProcess(cmds[i],
if beforeRunEvent != nil: beforeRunEvent(i)
q[r] = startProcess(cmds[i],
options = options + {poEvalCommand}) options = options + {poEvalCommand})
when defined(windows): when defined(windows):
w[r] = q[r].fProcessHandle w[rexit] = q[rexit].fProcessHandle
inc(i) inc(i)
else: else:
when defined(windows): when defined(windows):
for k in 0..wcount - 1: for k in 0..wcount - 1:
if w[k] == q[r].fProcessHandle: if w[k] == q[rexit].fProcessHandle:
w[k] = w[wcount - 1] w[k] = w[wcount - 1]
w[wcount - 1] = 0 w[wcount - 1] = 0
dec(wcount) dec(wcount)
break break
q[r] = nil q[rexit] = nil
dec(ecount) dec(ecount)
else: else:
for i in 0..high(cmds): for i in 0..high(cmds):
if beforeRunEvent != nil: if beforeRunEvent != nil: