ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/Development/ray/src/rt/RcontribSimulManager.cpp
(Generate patch)

Comparing ray/src/rt/RcontribSimulManager.cpp (file contents):
Revision 2.1 by greg, Tue Oct 29 00:36:54 2024 UTC vs.
Revision 2.22 by greg, Tue Nov 11 00:19:10 2025 UTC

# Line 24 | Line 24 | extern const char      HDRSTR[];
24   extern const char       BIGEND[];
25   extern const char       FMTSTR[];
26  
27 extern int              contrib;                /* computing contributions? */
28 extern int              lim_dist;               /* limit distance? */
29
27   // new/exclusive, overwrite if exists, or recover data
28   int     RSDOflags[] = {RDSwrite|RDSexcl|RDSextend, RDSwrite|RDSextend,
29                                  RDSread|RDSwrite};
# Line 38 | Line 35 | static const char      ROWZEROSTR[] = "NROWS=00000000000000
35   struct RcontribMod {
36          RcontribOutput *        opl;            // pointer to first output channel
37          char *                  params;         // parameters string
38 <        EPNODE *                binv;           // bin expression
38 >        EPNODE *                binv;           // bin expression (NULL if 1 bin)
39          int                     nbins;          // bin count this modifier
40          int                     coffset;        // column offset in bytes
41          DCOLORV                 cbin[1];        // bin accumulator (extends struct)
# Line 49 | Line 46 | struct RcontribMod {
46                                  }
47   };
48  
49 < // used to assign record calc to child
49 > // Struct used to assign record calculation to child
50   struct RowAssignment {
51          uint32                  row;            // row to do
52          uint32                  ac;             // accumulation count
53   };
54  
55 < // Our default data share function
59 < RdataShare *
60 < defDataShare(const char *name, RCOutputOp op, size_t siz)
61 < {
62 <        return new RdataShareMap(name, RSDOflags[op], siz);
63 < }
55 > static const char       ROW_DONE[] = "ROW FINISHED\n";
56  
57 < // Allocate rcontrib accumulator
58 < RcontribMod *
57 > // allocate rcontrib accumulator
58 > static RcontribMod *
59   NewRcMod(const char *prms, const char *binexpr, int ncbins)
60   {
61 <        if (ncbins <= 0) return NULL;
61 >        if (binexpr && !*binexpr) binexpr = NULL;
62          if (!prms) prms = "";
63 <        if (!binexpr | (ncbins == 1))
64 <                binexpr = "0";
65 <
63 >        if ((ncbins > 1) & !binexpr) {
64 >                error(USER, "missing bin expression");
65 >                return NULL;
66 >        }
67 >        if (ncbins < 1) ncbins = 1;
68 >        
69          RcontribMod *   mp = (RcontribMod *)ecalloc(1, sizeof(RcontribMod) +
70                                                  sizeof(DCOLORV)*(NCSAMP*ncbins-1) +
71                                                  strlen(prms)+1);
72  
73 +        if (binexpr) {                          // get/check bin expression
74 +                mp->binv = eparse(const_cast<char *>(binexpr));
75 +                if (mp->binv->type == NUM) {    // constant expression (0)?
76 +                        if ((int)evalue(mp->binv) != 0) {
77 +                                sprintf(errmsg, "illegal non-zero constant for bin (%s)",
78 +                                                binexpr);
79 +                                error(USER, errmsg);
80 +                        }
81 +                        if (ncbins > 1) {
82 +                                sprintf(errmsg, "bad bin count (%d should be 1)", ncbins);
83 +                                error(USER, errmsg);
84 +                        }
85 +                        epfree(mp->binv, true);
86 +                        mp->binv = NULL;
87 +                        prms = "";
88 +                        ncbins = 1;
89 +                }
90 +        }
91          mp->params = strcpy((char *)(mp->cbin + ncbins*NCSAMP), prms);
79        mp->binv = eparse(const_cast<char *>(binexpr));
92          mp->nbins = ncbins;
93          return mp;
94   }
95  
96 < // Free an RcontribMod
96 > // Free an RcontribMod (public for RcontribSimulManager constructor)
97   void
98   FreeRcMod(void *p)
99   {
100          if (!p) return;
101 <        epfree((*(RcontribMod *)p).binv, true);
101 >        EPNODE *        bep = (*(RcontribMod *)p).binv;
102 >        if (bep) epfree(bep, true);
103          efree(p);
104   }
105  
106 + // Get format identifier
107 + const char *
108 + formstr(int f)
109 + {
110 +        switch (f) {
111 +        case 'a': return("ascii");
112 +        case 'f': return("float");
113 +        case 'd': return("double");
114 +        case 'c': return(NCSAMP==3 ? COLRFMT : SPECFMT);
115 +        }
116 +        return("unknown");
117 + }
118 +
119 + // Standard file data share function
120 + RdataShare *
121 + fileDataShare(const char *name, RCOutputOp op, size_t siz)
122 + {
123 +        if (op == RCOrecover && access(name, R_OK|W_OK) < 0) {
124 +                sprintf(errmsg, "cannot recover from '%s'", name);
125 +                error(SYSTEM, errmsg);
126 +                return NULL;
127 +        }
128 +        RdataShare *    rds = new RdataShareFile(name, RSDOflags[op],
129 +                                                 siz*(op != RCOforce));
130 +                                                
131 +        if (!rds || (op == RCOforce && rds->Resize(siz) < siz)) {
132 +                delete rds;
133 +                sprintf(errmsg, "cannot create %lu byte output file '%s'",
134 +                                        (unsigned long)siz, name);
135 +                error(SYSTEM, errmsg);
136 +                return NULL;
137 +        }
138 +        return rds;
139 + }
140 +
141 + // Memory-mapped data share function
142 + RdataShare *
143 + mapDataShare(const char *name, RCOutputOp op, size_t siz)
144 + {
145 +        if (op == RCOrecover && access(name, R_OK|W_OK) < 0) {
146 +                sprintf(errmsg, "cannot recover from '%s'", name);
147 +                error(SYSTEM, errmsg);
148 +                return NULL;
149 +        }
150 +        RdataShare *    rds = new RdataShareMap(name, RSDOflags[op],
151 +                                                 siz*(op != RCOforce));
152 +
153 +        if (!rds || (op == RCOforce && rds->Resize(siz) < siz)) {
154 +                delete rds;
155 +                sprintf(errmsg, "cannot create %lu byte output map '%s'",
156 +                                        (unsigned long)siz, name);
157 +                error(SYSTEM, errmsg);
158 +                return NULL;
159 +        }
160 +        return rds;
161 + }
162 +
163   // Set output format ('f', 'd', or 'c')
164   bool
165   RcontribSimulManager::SetDataFormat(int ty)
# Line 133 | Line 203 | RcontribSimulManager::RctCall(RAY *r, void *cd)
203          if (!mp)
204                  return 0;               // not in our modifier list
205  
206 <        worldfunc(RCCONTEXT, r);        // compute bin #
207 <        set_eparams(mp->params);
208 <        double          bval = evalue(mp->binv);
209 <        if (bval <= -.5)
210 <                return 0;       // silently ignore negative bin index
211 <        DCOLORV *       dvp = (*mp)[int(bval + .5)];
206 >        if (rcp->HasFlag(RCcontrib) && sintens(r->rcol) <= FTINY)
207 >                return 0;               // zero contribution
208 >
209 >        int                     bi = 0; // get bin index
210 >        if (mp->binv) {
211 >                worldfunc(RCCONTEXT, r);
212 >                set_eparams(mp->params);
213 >                double          bval = evalue(mp->binv);
214 >                if (bval <= -.5)
215 >                        return 0;       // silently ignore negative bin index
216 >                bi = int(bval + .5);
217 >        }
218 >        DCOLORV *       dvp = (*mp)[bi];
219          if (!dvp) {
220 <                sprintf(errmsg, "bad bin number for '%s' (%.1f ignored)", mname, bval);
220 >                sprintf(errmsg, "bad bin number for '%s' (%d ignored)", mname, bi);
221                  error(WARNING, errmsg);
222                  return 0;
223          }
224          SCOLOR          contr;
225          raycontrib(contr, r, PRIMARY);          // compute coefficient
226 <        if (contrib)
226 >        if (rcp->HasFlag(RCcontrib))
227                  smultscolor(contr, r->rcol);    // -> value contribution
228 +
229          for (int i = 0; i < NCSAMP; i++)
230                  *dvp++ += contr[i];             // accumulate color/spectrum
231          return 1;
# Line 176 | Line 254 | bool
254   RcontribSimulManager::AddModifier(const char *modn, const char *outspec,
255                                  const char *prms, const char *binval, int bincnt)
256   {
257 <        if (!modn | !outspec | (bincnt <= 0) || !*modn | !*outspec) {
257 >        if (!modn | !outspec || !*modn | !*outspec) {
258                  error(WARNING, "ignoring bad call to AddModifier()");
259                  return false;
260          }
261 +        if (*outspec == '!') {
262 +                error(USER, "command output not supported by RcontribSimulManager");
263 +                return false;
264 +        }
265          if (!nChan) {                           // initial call?
266 +                if ((xres < 0) | (yres <= 0)) {
267 +                        error(USER, "xres, yres must be set before first modifier");
268 +                        return false;
269 +                }
270                  if (!SetDataFormat(dtyp))
271                          return false;
272                  nChan = NCSAMP;
273          } else if (nChan != NCSAMP) {
274 <                error(INTERNAL, "number of spectral channels must be fixed");
274 >                error(USER, "# spectral channels must be fixed in AddModifier()");
275                  return false;
276          }
277          if (Ready()) {
# Line 208 | Line 294 | RcontribSimulManager::AddModifier(const char *modn, co
294          const int       binndx = hasFormat(outspec, "diouxX");
295          int             bin0 = 0;
296          char            fnbuf[512];
297 <        if (!modndx | (modndx > binndx))
297 >        if (!modndx || (binndx > 0) & (modndx > binndx))
298                  sprintf(fnbuf, outspec, bin0, modn);
299          else
300                  sprintf(fnbuf, outspec, modn, bin0);
# Line 237 | Line 323 | RcontribSimulManager::AddModifier(const char *modn, co
323          mp->opl = op;                   // first (maybe only) output channel
324          if (modndx)                     // remember modifier if part of name
325                  op->omod = lp->key;
326 <        if (binndx > 0) {               // append output image/bin list
326 >        if (binndx) {                   // append output image/bin list
327                  op->rowBytes += dsiz;
328                  op->obin = bin0;
329                  for (bincnt = 1; bincnt < mp->nbins; bincnt++) {
330 <                        if (!modndx | (modndx > binndx))
330 >                        if (!modndx || (binndx > 0) &  (modndx > binndx))
331                                  sprintf(fnbuf, outspec, bin0+bincnt, modn);
332                          else
333                                  sprintf(fnbuf, outspec, modn, bin0+bincnt);
# Line 260 | Line 346 | RcontribSimulManager::AddModifier(const char *modn, co
346                          op->rowBytes += dsiz;
347                  }
348          } else                          // else send all results to this channel
349 <                op->rowBytes += bincnt*dsiz;
349 >                op->rowBytes += mp->nbins*dsiz;
350          return true;
351   }
352  
# Line 281 | Line 367 | RcontribSimulManager::AddModFile(const char *modfn, co
367          }
368          char            mod[MAXSTR];
369          while (fgetword(mod, sizeof(mod), fp))
370 <                if (!AddModifier(mod, outspec, prms, binval, bincnt))
370 >                if (!AddModifier(mod, outspec, prms, binval, bincnt)) {
371 >                        fclose(fp);
372                          return false;
373 +                }
374          fclose(fp);
375          return true;
376   }
377  
378 < // Run through current list of output struct's
379 < int
380 < RcontribSimulManager::GetOutputs(RoutputShareF *osF, void *cd) const
378 > // call-back to check if modifier has been loaded
379 > static int
380 > checkModExists(const LUENT *lp, void *p)
381   {
382 <        int     cnt = 0;
382 >        OBJECT  mod = modifier(lp->key);
383  
384 <        for (const RcontribOutput *op = outList; op; op = op->next) {
385 <                int     rv = 1;
386 <                if (osF && (rv = (*osF)(op, cd)) < 0)
387 <                        return rv;
388 <                cnt += rv;
389 <        }
302 <        return cnt;
384 >        if ((mod != OVOID) & (mod < nsceneobjs))
385 >                return 1;
386 >
387 >        sprintf(errmsg, "tracked modifier '%s' not found in main scene", lp->key);
388 >        error(WARNING, errmsg);
389 >        return 0;
390   }
391  
392   // Prepare output channels and return # completed rows
# Line 307 | Line 394 | int
394   RcontribSimulManager::PrepOutput()
395   {
396          if (!outList || !RtraceSimulManager::Ready()) {
397 <                error(INTERNAL, "PrepOutput() called before octree & modifiers assigned");
397 >                error(INTERNAL, "PrepOutput() called before octree & modifiers set");
398                  return -1;
399          }
400 +        if (!cdsF) {
401 +                error(INTERNAL, "missing RdataShare constructor call (cdsF)");
402 +                return -1;
403 +        }
404 +        if (lu_doall(&modLUT, checkModExists, NULL) < 0)
405 +                return -1;
406 +
407 +        outList->nRows = yres * (xres + !xres); // all outputs have same #rows
408          int     remWarnings = 20;
409          for (RcontribOutput *op = outList; op; op = op->next) {
410                  if (op->rData) {
411                          error(INTERNAL, "output channel already open in PrepOutput()");
412                          return -1;
413                  }
414 <                op->nRows = yres * (xres + !xres);
414 >                op->nRows = outList->nRows;
415                  op->rData = (*cdsF)(op->ofname, outOp,
416                                          GetHeadLen()+1024 + op->nRows*op->rowBytes);
417                  freeqstr(op->ofname); op->ofname = NULL;
# Line 325 | Line 420 | RcontribSimulManager::PrepOutput()
420                          if (rd < 0)
421                                  return -1;
422                          if (rd >= op->nRows) {
423 <                                if (remWarnings >= 0) {
424 <                                        sprintf(errmsg, "recovered output '%s' already done",
423 >                                if (remWarnings > 0) {
424 >                                        sprintf(errmsg, "recovered output '%s' is complete",
425                                                          op->GetName());
426 <                                        error(WARNING, remWarnings ? errmsg : "etc...");
332 <                                        remWarnings--;
426 >                                        error(WARNING, --remWarnings ? errmsg : "etc...");
427                                  }
428                                  rd = op->nRows;
429                          }
# Line 341 | Line 435 | RcontribSimulManager::PrepOutput()
435                                  !op->rData->Resize(op->begData + op->nRows*op->rowBytes))
436                          return -1;              // calls error() for us
437          }
344        if (lim_dist)                           // XXX where else to put this?
345                rtFlags |= RTlimDist;
346        else
347                rtFlags &= ~RTlimDist;
348
438          rowsDone.NewBitMap(outList->nRows);     // create row completion map
439          rowsDone.ClearBits(0, rInPos, true);
440 <        return rInPos;
440 >        return nrDone = rInPos;
441   }
442  
443   // Create header in open write-only channel
# Line 376 | Line 465 | RcontribOutput::NewHeader(const RcontribSimulManager *
465          strcpy(hdr+begData, ROWZEROSTR);
466          rowCountPos = begData+LNROWSTR;
467          begData += sizeof(ROWZEROSTR)-1;
468 <        if (!xres | (rowBytes > esiz)) {
468 >        if (!rcp->xres | (rowBytes > esiz)) {
469                  sprintf(hdr+begData, "NCOLS=%d\n", int(rowBytes/esiz));
470                  begData += strlen(hdr+begData);
471          }
472          sprintf(hdr+begData, "%s%d\n", NCOMPSTR, NCSAMP);
473          begData += strlen(hdr+begData);
474          if (NCSAMP > 3) {
475 <                sprintf(hdr+begData, "%s %f %f %f %f\n", WLSPLTSTR,
475 >                sprintf(hdr+begData, "%s %g %g %g %g\n", WLSPLTSTR,
476                                  WLPART[0], WLPART[1], WLPART[2], WLPART[3]);
477                  begData += strlen(hdr+begData);
478          }
# Line 414 | Line 503 | RcontribOutput::NewHeader(const RcontribSimulManager *
503                          hdr[begData++] = ' ';
504          hdr[begData++] = '\n';          // EOL for data format
505          hdr[begData++] = '\n';          // end of nominal header
506 <        if ((xres > 0) & (rowBytes == esiz)) {  // tack on resolution string?
507 <                sprintf(hdr+begData, PIXSTDFMT, yres, xres);
506 >        if ((rcp->xres > 0) & (rowBytes == esiz)) {     // tack on resolution string?
507 >                sprintf(hdr+begData, PIXSTDFMT, rcp->yres, rcp->xres);
508                  begData += strlen(hdr+begData);
509          }
510          return rData->ReleaseMemory(hdr, RDSwrite);
# Line 461 | Line 550 | RcontribOutput::CheckHeader(const RcontribSimulManager
550                  return -1;
551          }
552                                                  // check format
553 <        if (!(cp = findArgs(hdr, FMTSTR, begData)) || strcmp(cp, formstr(etyp))) {
553 >        if (!(cp = findArgs(hdr, FMTSTR, begData)) ||
554 >                                strncmp(cp, formstr(etyp), strlen(formstr(etyp)))) {
555                  sprintf(errmsg, "expected %s%s in '%s'", FMTSTR, formstr(etyp), GetName());
556                  error(USER, errmsg);
557                  return -1;
558          }
559                                                  // check #columns
560 <        if (((cp = findArgs(hdr, "NCOLS=", begData)) && atoi(cp)*esiz != rowBytes) ||
561 <                        !xres | (rowBytes > esiz)) {
562 <                sprintf(errmsg, "expected NCOLS=%d in '%s'",
473 <                                int(rowBytes/esiz), GetName());
560 >        if ((cp = findArgs(hdr, "NCOLS=", begData)) ? (atoi(cp)*esiz != rowBytes)
561 >                                                    : (!rcp->xres | (rowBytes > esiz))) {
562 >                sprintf(errmsg, "expected NCOLS=%d in '%s'", int(rowBytes/esiz), GetName());
563                  error(USER, errmsg);
564                  return -1;
565          }
# Line 483 | Line 572 | RcontribOutput::CheckHeader(const RcontribSimulManager
572          rowCountPos = cp - hdr;
573          int     rlast = atoi(cp);
574          begData++;                              // advance past closing EOL
575 <        if ((xres > 0) & (rowBytes == esiz)) {  // check/skip resolution string?
575 >        if ((rcp->xres > 0) & (rowBytes == esiz)) {     // check/skip resolution string?
576                  char    rbuf[64];
577 <                sprintf(rbuf, PIXSTDFMT, yres, xres);
577 >                sprintf(rbuf, PIXSTDFMT, rcp->yres, rcp->xres);
578                  int     rlen = strlen(rbuf);
579                  if (strncmp(rbuf, hdr+begData, rlen)) {
580                          sprintf(errmsg, "bad resolution string in '%s'", GetName());
# Line 512 | Line 601 | RcontribSimulManager::ResetRow(int r)
601                          return false;
602  
603          rowsDone.ClearBits(r, rInPos-r, false);
604 <        rInPos = r;
604 >        nrDone = rInPos = r;
605          return true;
606   }
607  
# Line 559 | Line 648 | putModContrib(const LUENT *lp, void *p)
648                  }
649                  } break;
650          default:
651 <                error(CONSISTENCY, "unsupported output type in sendModContrib()");
651 >                error(CONSISTENCY, "unsupported output type in putModContrib()");
652                  return -1;
653          }
654                                                  // clear for next tally
# Line 578 | Line 667 | RcontribSimulManager::ComputeRecord(const FVECT orig_d
667                  return 0;
668          }
669          if (nkids > 0) {                        // in parent process?
670 <                int     k = GetChild();         // updates output rows
671 <                if (k < 0) return -1;           // can't really happen
670 >                int     k = GetChild(false);    // updates output rows
671 >                if (k < 0) return -1;           // someone died?
672                  RowAssignment   rass;
673                  rass.row = kidRow[k] = rInPos++;
674                  rass.ac = accum;
# Line 624 | Line 713 | RcontribSimulManager::GetChild(bool forceWait)
713                  return -1;
714                                                  // take inventory
715          int     pn, n = 0;
716 <        fd_set  writeset, errset;
717 <        FD_ZERO(&writeset); FD_ZERO(&errset);
716 >        fd_set  readset, errset;
717 >        FD_ZERO(&readset); FD_ZERO(&errset);
718          for (pn = nkids; pn--; ) {
719                  if (kidRow[pn] < 0) {           // child already ready?
720                          if (forceWait) continue;
721                          return pn;              // good enough
722                  }
723 <                FD_SET(kid[pn].w, &writeset);   // will check on this one
724 <                FD_SET(kid[pn].w, &errset);
725 <                if (kid[pn].w >= n)
726 <                        n = kid[pn].w + 1;
723 >                FD_SET(kid[pn].r, &readset);    // will check on this one
724 >                FD_SET(kid[pn].r, &errset);
725 >                if (kid[pn].r >= n)
726 >                        n = kid[pn].r + 1;
727          }
728          if (!n)                                 // every child is idle?
729                  return -1;
730                                                  // wait on "busy" child(ren)
731 <        while ((n = select(n, NULL, &writeset, &errset, NULL)) <= 0)
731 >        while ((n = select(n, &readset, NULL, &errset, NULL)) <= 0)
732                  if (errno != EINTR) {
733                          error(SYSTEM, "select call failed in GetChild()");
734                          return -1;
735                  }
736 +        char    buf[sizeof(ROW_DONE)] = "X";
737          pn = -1;                                // get flags set by select
738          for (n = nkids; n--; )
739                  if (kidRow[n] >= 0 &&
740 <                                FD_ISSET(kid[n].w, &writeset) |
741 <                                FD_ISSET(kid[n].w, &errset)) {
740 >                                FD_ISSET(kid[n].r, &readset) |
741 >                                FD_ISSET(kid[n].r, &errset)) {
742 >                                                // check for error
743 >                        if (FD_ISSET(kid[n].r, &errset) ||
744 >                                        read(kid[n].r, buf, sizeof(ROW_DONE)) <= 0 ||
745 >                                        memcmp(buf, ROW_DONE, sizeof(ROW_DONE)))
746 >                                return -1;
747                                                  // update output row counts
748                          UpdateRowsDone(kidRow[n]);
749 <                        kidRow[n] = -1;         // flag it available
749 >                        kidRow[n] = -1;         // flag child available
750                          pn = n;
751                  }
752          return pn;
# Line 665 | Line 760 | RcontribSimulManager::UpdateRowsDone(int r)
760                  error(WARNING, "redundant call to UpdateRowsDone()");
761                  return false;
762          }
763 <        int     nDone = GetRowFinished();
764 <        if (nDone <= r)
763 >        GetRowFinished();
764 >        if (nrDone <= r)
765                  return true;                    // nothing to update, yet
766          for (RcontribOutput *op = outList; op; op = op->next)
767 <                if (!op->SetRowsDone(nDone))
767 >                if (!op->SetRowsDone(nrDone))
768                          return false;
769          return true;                            // up-to-date
770   }
# Line 689 | Line 784 | RcontribSimulManager::RunChild()
784                          error(CONSISTENCY, "bad accumulator count in child");
785                          exit(1);
786                  }
787 <                if (rass.ac > accum)
788 <                        vecList = (FVECT *)erealloc(vecList,
789 <                                                sizeof(FVECT)*2*rass.ac);
787 >                if (rass.ac > accum) {
788 >                        efree(vecList);
789 >                        vecList = (FVECT *)emalloc(sizeof(FVECT)*2*rass.ac);
790 >                }
791                  accum = rass.ac;
792                  rInPos = rass.row;
793  
# Line 701 | Line 797 | RcontribSimulManager::RunChild()
797  
798                  if (ComputeRecord(vecList) <= 0)
799                          exit(1);
800 +                                                // signal this row is done
801 +                if (write(1, ROW_DONE, sizeof(ROW_DONE)) != sizeof(ROW_DONE))
802 +                        exit(1);
803          }
804          if (nr) {
805                  error(SYSTEM, "read error in child process");
# Line 726 | Line 825 | RcontribSimulManager::StartKids(int n2go)
825          fflush(stdout);                         // shouldn't use, anyway
826          while (nkids < n2go) {
827                  kid[nkids] = sp_inactive;
729                kid[nkids].w = dup(1);
730                kid[nkids].flags |= PF_FILT_OUT;
828                  int     rv = open_process(&kid[nkids], NULL);
829                  if (!rv) {                      // in child process?
830 <                        while (nkids-- > 0)
830 >                        while (nkids-- > 0) {
831 >                                close(kid[nkids].r);
832                                  close(kid[nkids].w);
833 +                        }
834                          free(kid); free(kidRow);
835                          kid = NULL; kidRow = NULL;
737                        rowsDone.NewBitMap(0);
836                          RunChild();             // should never return
837                          _exit(1);
838                  }
# Line 783 | Line 881 | RcontribSimulManager::SetThreadCount(int nt)
881                  return 0;
882          }
883          if (nt < 0)
884 <                return nkids;
884 >                return NThreads();
885          if (!nt) nt = GetNCores();
886          int     status = 0;
887          if (nt == 1)
# Line 796 | Line 894 | RcontribSimulManager::SetThreadCount(int nt)
894                  sprintf(errmsg, "non-zero (%d) status from child", status);
895                  error(WARNING, errmsg);
896          }
897 <        return nkids;
897 >        return NThreads();
898   }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)