From: Ian Jackson Date: Tue, 28 Dec 2010 01:16:58 +0000 (+0000) Subject: movpos: wip multiple movfeatkinds in one request; working on indep code X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=87be2f631bf94255e2025ce55b09e119600a1c7c;p=trains.git movpos: wip multiple movfeatkinds in one request; working on indep code --- diff --git a/hostside/errorcodes.h.gen b/hostside/errorcodes.h.gen index 7ccd989..8536d2d 100755 --- a/hostside/errorcodes.h.gen +++ b/hostside/errorcodes.h.gen @@ -3,7 +3,8 @@ @f= qw( OK MovFeatTooLate - MovFeatKindsCombination + MovFeatTooManyMethods + MovFeatTooManyMotions MovFeatReservationInapplicable MovFeatRouteNotFound BufferFull diff --git a/hostside/movpos.c b/hostside/movpos.c index 632fbde..845cee0 100644 --- a/hostside/movpos.c +++ b/hostside/movpos.c @@ -43,8 +43,8 @@ typedef struct Method Method; typedef struct Change Change; struct Change { /* valid in: filled in by and when: */ - Method *meth; /* PQ indep after allocate() */ - MovPosChange *indep; /* PQ indep after allocate() */ + Method *meth; /* PQ indep after prepare() */ + MovPosChange *indep; /* PQ indep after prepare() */ /* kind-specific data follows */ /* varies kind-specific code, varies */ } Change; /* `actual' contains the kind's public opinion about the physical @@ -67,7 +67,7 @@ struct Method { Segment *move, int n_motions, const Motion *motions, int ms, int confirming, - Change *chg_r, /* U->P; err: U->U; may be 0 */ + Change *chg_r, /* 0->P; err: 0->0; may be 0 */ int *cost_r /* may be 0 */); ErrorCode (*consider)(Method *m, /* TYE->T */ Change *remove, /* Q->P; err: Q->Q */ @@ -78,7 +78,7 @@ struct Method { ErrorCode (*check)(Method *m); /* TYE->Y; err: TYE->TYE */ void (*execute)(Method *m); /* EY->E */ - void (*all_abandon)(Method *m); + void (*all_abandon)(Method *m); /* I */ }; const char *movpos_pname(Segment *move, MovPosComb poscomb) { @@ -241,8 +241,8 @@ static void fsq_queue_remove_item(FsqQueue *q, FsqReq *r) { fsq_queue_remove_index(q, i); } -static FsqQueue *fsq_item_queue(FsqMethod *m, FsqReq *r) { - return r->motions[0].i ? &m->f.confirmed : &m->f.reserved; +static FsqQueue *fsq_item_queue(FsqMethod *m, FsqReq *r) + { return r->motions[0].i ? &m->f.confirmed : &m->f.reserved; } #define WHICH(wh) \ (whichr= wh##r, \ @@ -689,102 +689,206 @@ static void indep_change_done(Method *m, Change *chg) { free(indep); } +#define EVAL_MAX_METHODS 2 +#define EVAL_MAX_MOTIONS 2 + static ErrorCode evaluate_target(Segment *move, MovPosComb target, MovPosComb startpoint, - int *n_changes_r, - Change *changes_r[N_METHODS], - int *cost_r) { + int ms, int confirming, + MovPosChange *indep_r /* 0 ok */, + int *cost_r /* 0 ok */) { + static int n_meths; + static Method *meths[EVAL_MAX_METHODS]; + static int n_motions[EVAL_MAX_METHODS]; + static Motion meths[EVAL_MAX_METHODS][EVAL_MAX_MOTIONS]; + const SegmentInfo *movei= move->i; int feat; const MovFeatInfo *feati; - MovFeatKind kind; - int n_changes; - Method *change_methods[N_METHODS]; - Motion *change_motions[N_METHODS]; - int i; - DPRINTF(movpos,eval, "%s/%s <-%s\n", move->i->pname, + MovPosChange *indep=0; + + DPRINTF(movpos,eval, "%s/%s <-%s", move->i->pname, movpos_pname(move,target), movpos_pname(move,startpoint)); if (!SOMEP(startpoint)) { startpoint= movpos_poscomb_actual(move); - DPRINTF(movpos,eval, " actual <-%s\n", + fixme actual plumbing etc; + DPRINTF(movpos,eval, " actual <-%s\n", movpos_pname(move,startpoint)); } - n_changes= 0; + n_meths= 0; for (feat=0, feati=movei->movfeats, tchanges=0, kind= mfk_none; featn_movfeats; feat++, feati++) { if (!change_needed(feati,startpoint,target)) continue; - for (i=0; iweight % feati->posns; + Method *meth= methods[kind]; + + int methi; + for (methi=0; methi= EVAL_MAX_METHODS) return EC_MovFeatTooManyMethods; + meths[methi]= meth; + n_motions[methi]= 0; + DPRINTF(movpos,eval, " meths[%d]=%s", methi,meth->pname); + + found_method: + int motioni= ++n_motions[methi]; + if (motioni >= EVAL_MAX_MOTIONS) return EC_MovFeatTooManyMotions; + DPRINTF(movpos,eval, " motion[%d][%d]=%s%d", + methi,motioni,feati->pname,posn); + motions[methi][motioni].i= feati; + motions[methi][motioni].posn= posn; + } + + if (indep_r) { + DPRINTF(movpos,eval, " alloc"); + indep= mmalloc(sizeof(*indep) + sizeof(Change*) * n_meths); + memset(indep->changes, 0, sizeof(Change*) * n_meths); + indep->move= move; + indep->start= fixme startpoint; + indep->actual= fixme startbfixpoint; + } + DPRINTF(movpos,eval, "\n"); + + int totalcost= 0; + + for (int changei=0; changeiprepare(meth,move, + n_motions[changei],motions[changei], + ms, confirming, + indep ? &indep->changes[changei] : 0, + thiscost); + if (ec) goto x; + if (indep) { + Change *chg= indep->changes[changei]; + chg->meth= meth; + chg->indep= indep; + } + totalcost += thiscost; + } + + if (indep_r) *indep_r= indep; + if (cost_r) *cost_r= totalcost; + DPRINTF(movpos,eval, "%s/%s ok cost=%d\n", move->i->pname, + movpos_pname(move,target), totalcost); + return 0; + + x: + DPRINTF(movpos,eval, "%s/%s abandon %s\n", move->i->pname, + movpos_pname(move,target), totalcost, ec2str(ec)); + indep_dispose(indep); + return ec; +} + +static ErrorCode +indep_swap(MovPosChange *remv, MovPosChange *inst) { + /* does consider and check */ + assert(inst->n_changes <= 32); + assert(remv->n_changes <= 32); + uint32_t inst_done, remv_done; + int inst2remv[inst->n_changes]; /* valid only if inst_done; -ve => none */ + + int ii, jj; + + for (ii=0; iin_changes; ii++) { + Method *meth= inst->changes[ii].meth; + for (jj=remv->n_changes-1; jj>=0; jj++) + if (remv->changes[jj].meth == meth) break; + ec= meth->consider(meth, + jj>=0 ? remv->changes[jj] : 0, + inst->changes[ii]); + if (ec) goto x; - tchanges++; - if (kind && feati->kind != kind) return -1; - kind= feati->kind; + inst_done |= (1UL << ii); + inst2remv[ii]= jj; + if (jj>=0) remv_done |= (1UL << jj); + + ec= meth->check(meth); + if (ec) goto x; + } + for (jj=0; jjn_changes; jj++) { + if (remv_done & (1UL << jj)) continue; + ec= meth->consider(meth, remv->changes[jj], 0); + assert(!ec); + ec= meth->check(meth); + assert(!ec); + /* remv_done |= (1UL << jj); + not needed because we never roll back from here */ } + return 0; - if (kind_r) *kind_r= kind; - DPRINTF(movpos,eval, "changes=%d kind=%s\n", - tchanges, methods[kind]->pname); - return tchanges; + x: + for (ii=0; iin_changes; ii++) { + if (!(inst_done & (1UL << ii))) continue; + Method *meth= inst->changes[ii].meth; + jj= inst2remv[ii]; + ec= meth->consider(meth, + inst->changes[ii], + jj>=0 ? remv->changes[jj] : 0); + assert(!ec); + ec= meth->check(meth); + assert(!ec); + } + /* we do not need to unwind methods for which we are only removing + * since we never roll back after starting those */ + return ec; } +static void indep_execute(void) { + for (Method **methwalk= methods; + (meth= *methwalk); + methwalk++) { + meth->execute(meth); + } +} +static void indep_dispose(MovPosChange *indep) { + if (!indep) return; + + for (int changei=0; changein_changes; changei++) { + Change *chg= indep->changes[changei]; + Method *meth= chg->meth; + if (chg) + meth->dispose(meth, chg); + } + free(indep); +} ErrorCode movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r, MovPosComb target, MovPosComb startpoint /*as for findcomb*/) { - MovFeatKind kind= mfk_none; ErrorCode ec; - int nchanges; - - int n_changes; - Change *changes[N_METHODS]; + MovPosChange *indep= 0; DPRINTF(movpos,reserve, "%s/%s maxdelay=%dms startpoint=%s\n", move->i->pname, movpos_pname(move,target), maxdelay_ms, movpos_pname(move,startpoint)); - evaluate_target(move,target,startpoint, &n_changes,&changes); - - - if (nchanges==-1) return EC_MovFeatKindsCombination; + ec= evaluate_target(move,target, startpoint, + ms,1, + &indep, 0); + if (ec) return ec; - Method *meth= methods[kind]; - DPRINTF(movpos,reserve, "allocate %s:%d...\n", - meth->pname, nchanges); - Change *chg= mp_allocate(meth, move, nchanges, target); - ec= meth->reserve(meth, chg, move, maxdelay_ms); - DPRINTF(movpos,reserve, "reserve => %s\n",errorcodelist[ec]); + ec= indep_consider(0, indep); if (ec) goto x; - *res_r= chg; + indep_execute(); return 0; x: - movpos_unreserve(chg); + indep_dispose(indep); + indep_execute(); return ec; } - - - - - - -static Change *mp_allocate(Method *meth, Segment *move, - int alloc_motions, MovPosComb target) { - assert(sta_state >= Sta_Resolving || sta_state == Sta_Manual); - Change *chg= meth->allocate(meth, alloc_motions); - chg->meth= meth; - chg->move= move; - chg->intent= target; - return chg; -} - static int change_needed(const MovFeatInfo *feati, MovPosComb startpoint, MovPosComb target) { int r; @@ -801,7 +905,7 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd, MovPosComb startpoint, MovPosComb *chosen_r) { const SegmentInfo *movei= move->i; MovPosComb tcomb, bestcomb=-1; - int tchanges, bestchanges=INT_MAX; + int tcost, bestcost=INT_MAX; const SegPosCombInfo *pci; for (tcomb=0, pci=movei->poscombs; @@ -813,25 +917,24 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd, if (fwd && !(fwd ==tback || fwd ==tfwd)) continue; /* we have to search for the one which is least effort */ - tchanges= evaluate_target(move,tcomb,startpoint,0); + ec= evaluate_target(move,tcomb,startpoint, -1,0, 0,&tcost); + if (ec) return ec; - if (tchanges==-1) - /* mixed kinds */ - tchanges= INT_MAX-1; - - if (tchanges >= bestchanges) /* prefer low-numbered movposcombs */ + if (tcost >= bestcost) /* prefer low-numbered movposcombs */ continue; bestcomb= tcomb; - bestchanges= tchanges; + bestcost= tcost; } if (chosen_r) *chosen_r= bestcomb; return - bestchanges==INT_MAX ? EC_MovFeatRouteNotFound : - bestchanges==INT_MAX-1 ? EC_MovFeatKindsCombination : + bestcost==INT_MAX ? EC_MovFeatRouteNotFound : 0; } + +NEW CODE UP TO HERE + ErrorCode movpos_change(Segment *move, MovPosComb target, int maxdelay_ms, MovPosChange *chg) { const SegmentInfo *movei= move->i; @@ -860,21 +963,7 @@ ErrorCode movpos_change(Segment *move, MovPosComb target, int n_motions=0; Motion motions[movei->n_movfeats]; - for (feat=0, feati=movei->movfeats; - featn_movfeats; - feat++, feati++) { - if (!change_needed(feati,actual,target)) - continue; - MovPosComb posn= target / feati->weight % feati->posns; - if (kind) { - if (feati->kind != kind) { ec= EC_MovFeatKindsCombination; goto x; } - } else { - kind= feati->kind; - } - motions[n_motions].i= feati; - motions[n_motions].posn= posn; - n_motions++; - } + there was code here to fill in motions Method *meth= methods[kind]; @@ -1077,3 +1166,14 @@ in points_all_abandon * * seg->moving and ->motion is in one of the states UC + +static Change *mp_allocate(Method *meth, Segment *move, + int alloc_motions, MovPosComb target) { + assert(sta_state >= Sta_Resolving || sta_state == Sta_Manual); + Change *chg= meth->allocate(meth, alloc_motions); + chg->meth= meth; + chg->move= move; + chg->intent= target; + return chg; +} +