| 23 |
|
static BINQ *free_bq = NULL; /* free queue entries */ |
| 24 |
|
|
| 25 |
|
static SUBPROC kida[MAXPROCESS]; /* child processes */ |
| 26 |
+ |
static FILE *inq_fp[MAXPROCESS]; /* input streams */ |
| 27 |
|
|
| 28 |
|
|
| 29 |
|
/* Get new (empty) bin queue entry */ |
| 123 |
|
} |
| 124 |
|
|
| 125 |
|
|
| 126 |
< |
/* Queue output, catching up with and freeing FIFO entries when possible */ |
| 127 |
< |
static int |
| 126 |
> |
/* Queue values for later output */ |
| 127 |
> |
static void |
| 128 |
|
queue_output(BINQ *bp) |
| 129 |
|
{ |
| 129 |
– |
int nout = 0; |
| 130 |
|
BINQ *b_last, *b_cur; |
| 131 |
– |
int i; |
| 131 |
|
|
| 132 |
|
if (accumulate <= 0) { /* just accumulating? */ |
| 133 |
|
if (out_bq == NULL) { |
| 137 |
|
add_modbin(out_bq, bp); |
| 138 |
|
free_binq(bp); |
| 139 |
|
} |
| 140 |
< |
return(0); |
| 140 |
> |
return; |
| 141 |
|
} |
| 142 |
|
b_last = NULL; /* else insert in output queue */ |
| 143 |
|
for (b_cur = out_bq; b_cur != NULL && b_cur->ndx < bp->ndx; |
| 150 |
|
bp->next = out_bq; |
| 151 |
|
out_bq = bp; |
| 152 |
|
} |
| 153 |
< |
if (accumulate > 1) { /* merge accumulation entries */ |
| 154 |
< |
b_cur = out_bq; |
| 155 |
< |
while (b_cur->next != NULL) { |
| 156 |
< |
if (b_cur->n2add <= 0 || |
| 157 |
< |
(b_cur->ndx-1)/accumulate != |
| 158 |
< |
(b_cur->next->ndx-1)/accumulate) { |
| 159 |
< |
b_cur = b_cur->next; |
| 160 |
< |
continue; |
| 161 |
< |
} |
| 163 |
< |
add_modbin(b_cur, b_cur->next); |
| 164 |
< |
b_cur->n2add--; |
| 165 |
< |
b_last = b_cur->next; |
| 166 |
< |
b_cur->next = b_last->next; |
| 167 |
< |
b_last->next = NULL; |
| 168 |
< |
free_binq(b_last); |
| 153 |
> |
if (accumulate <= 1) /* no accumulating? */ |
| 154 |
> |
return; |
| 155 |
> |
b_cur = out_bq; /* else merge accumulation entries */ |
| 156 |
> |
while (b_cur->next != NULL) { |
| 157 |
> |
if (b_cur->n2add <= 0 || |
| 158 |
> |
(b_cur->ndx-1)/accumulate != |
| 159 |
> |
(b_cur->next->ndx-1)/accumulate) { |
| 160 |
> |
b_cur = b_cur->next; |
| 161 |
> |
continue; |
| 162 |
|
} |
| 163 |
+ |
add_modbin(b_cur, b_cur->next); |
| 164 |
+ |
b_cur->n2add--; |
| 165 |
+ |
b_last = b_cur->next; |
| 166 |
+ |
b_cur->next = b_last->next; |
| 167 |
+ |
b_last->next = NULL; |
| 168 |
+ |
free_binq(b_last); |
| 169 |
|
} |
| 170 |
< |
/* output ready results */ |
| 170 |
> |
} |
| 171 |
> |
|
| 172 |
> |
|
| 173 |
> |
/* Get current with output FIFO by producing ready results */ |
| 174 |
> |
static int |
| 175 |
> |
output_catchup() |
| 176 |
> |
{ |
| 177 |
> |
int nout = 0; |
| 178 |
> |
BINQ *bp; |
| 179 |
> |
int i; |
| 180 |
> |
|
| 181 |
> |
if (accumulate <= 0) /* just accumulating? */ |
| 182 |
> |
return(0); |
| 183 |
> |
/* else output ready results */ |
| 184 |
|
while (out_bq != NULL && (out_bq->ndx == lastdone+1) & !out_bq->n2add) { |
| 185 |
< |
b_cur = out_bq; /* pop off first entry */ |
| 186 |
< |
out_bq = b_cur->next; |
| 187 |
< |
b_cur->next = NULL; |
| 185 |
> |
bp = out_bq; /* pop off first entry */ |
| 186 |
> |
out_bq = bp->next; |
| 187 |
> |
bp->next = NULL; |
| 188 |
|
for (i = 0; i < nmods; i++) /* output record */ |
| 189 |
< |
mod_output(b_cur->mca[i]); |
| 189 |
> |
mod_output(bp->mca[i]); |
| 190 |
|
end_record(); |
| 191 |
< |
free_binq(b_cur); /* free this entry */ |
| 191 |
> |
free_binq(bp); /* free this entry */ |
| 192 |
|
lastdone += accumulate; |
| 193 |
|
++nout; |
| 194 |
|
} |
| 259 |
|
kida[nchild].w = p0[1]; |
| 260 |
|
kida[nchild].pid = pid; |
| 261 |
|
kida[nchild].running = -1; |
| 262 |
+ |
inq_fp[nchild] = fdopen(p1[0], "rb"); |
| 263 |
+ |
if (inq_fp[nchild] == NULL) |
| 264 |
+ |
error(SYSTEM, "out of memory in in_rchild()"); |
| 265 |
|
++nchild; |
| 266 |
|
} |
| 267 |
|
return(0); /* parent return value */ |
| 275 |
|
{ |
| 276 |
|
int status; |
| 277 |
|
|
| 278 |
< |
while (nchild-- > 0) |
| 278 |
> |
while (nchild-- > 0) { |
| 279 |
> |
kida[nchild].r = -1; /* close(-1) error is ignored */ |
| 280 |
|
if ((status = close_process(&kida[nchild])) > 0) { |
| 281 |
|
sprintf(errmsg, |
| 282 |
|
"rendering process returned bad status (%d)", |
| 283 |
|
status); |
| 284 |
|
error(WARNING, errmsg); |
| 285 |
|
} |
| 286 |
+ |
fclose(inq_fp[nchild]); /* performs actual close() */ |
| 287 |
+ |
} |
| 288 |
|
} |
| 289 |
|
|
| 290 |
|
|
| 291 |
< |
/* Wait for the next available child */ |
| 291 |
> |
/* Wait for the next available child, managing output queue as well */ |
| 292 |
|
static int |
| 293 |
|
next_child_nq(int force_wait) |
| 294 |
|
{ |
| 295 |
< |
fd_set readset, errset; |
| 296 |
< |
int i, j, n, nr; |
| 295 |
> |
static struct timeval polling; |
| 296 |
> |
struct timeval *pmode = force_wait | (accumulate <= 0) ? |
| 297 |
> |
(struct timeval *)NULL : &polling; |
| 298 |
> |
fd_set readset, errset; |
| 299 |
> |
int i, j, n, nr; |
| 300 |
|
|
| 301 |
|
if (!force_wait) /* see if there's one free */ |
| 302 |
|
for (i = nchild; i--; ) |
| 316 |
|
} |
| 317 |
|
if (!nr) /* nothing going on */ |
| 318 |
|
return(-1); |
| 319 |
< |
if (nr > 1) { /* call select if multiple busy */ |
| 319 |
> |
tryagain: |
| 320 |
> |
if (pmode == NULL) /* about to block, so catch up */ |
| 321 |
> |
output_catchup(); |
| 322 |
> |
if ((nr > 1) | (pmode == &polling)) { |
| 323 |
|
errno = 0; |
| 324 |
< |
if (select(n, &readset, NULL, &errset, NULL) < 0) |
| 324 |
> |
nr = select(n, &readset, NULL, &errset, pmode); |
| 325 |
> |
if (!nr & (pmode == &polling)) { |
| 326 |
> |
pmode = NULL; /* try again, blocking this time */ |
| 327 |
> |
goto tryagain; |
| 328 |
> |
} |
| 329 |
> |
if (nr <= 0) |
| 330 |
|
error(SYSTEM, "select call error in next_child_nq()"); |
| 331 |
|
} else |
| 332 |
|
FD_ZERO(&errset); |
| 341 |
|
bq->ndx = kida[i].running; |
| 342 |
|
/* read from child */ |
| 343 |
|
for (j = 0; j < nmods; j++) { |
| 344 |
< |
n = sizeof(DCOLOR)*bq->mca[j]->nbins; |
| 345 |
< |
nr = readbuf(kida[i].r, (char *)bq->mca[j]->cbin, n); |
| 344 |
> |
n = bq->mca[j]->nbins; |
| 345 |
> |
nr = fread(bq->mca[j]->cbin,sizeof(DCOLOR),n,inq_fp[i]); |
| 346 |
|
if (nr != n) |
| 347 |
|
error(SYSTEM, "read error from render process"); |
| 348 |
|
} |