X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=blobdiff_plain;f=hostside%2Fmovpos.c;h=75a139d93b73e7cfdac8615ea96ecea8631a5386;hb=fe3d5809b4a1f0b8186d3e3fb76dc36ef6d08718;hp=e919f4729c9fdea93e86a02887f688bfcb24907e;hpb=726bb4c3cf2e6fb7d8b848c5ec6e30cd76ba5c6b;p=trains.git diff --git a/hostside/movpos.c b/hostside/movpos.c index e919f47..75a139d 100644 --- a/hostside/movpos.c +++ b/hostside/movpos.c @@ -14,10 +14,15 @@ typedef struct { typedef struct Method Method; typedef struct Change Change; +#define PRunkx PRIx32 +typedef uint32_t UnkMap; + typedef struct MovPosChange { Segment *move; /* everything beyond here is private for indep */ - MovPosComb actual, target; + MovPosComb actualpos, target; + UnkMap actualunk; /* bit per movfeat, set iff actualpos contains dummy 0 */ + int refcount; int n_changes; Change *changes[]; } Indep; @@ -35,9 +40,9 @@ static void method_change_done(Method *m, Change *chg); * has been done. The method-independent code will take care of * updating move->movposcomb. etc. * - * REENTRANCY: must NOT be called from within a call to the method's - * execute() (and of course cannot legally be called from within - * prepare, consider, check or dispose). + * REENTRANCY: May be called from within a call to the method's + * execute(). Of course cannot legally be called from within + * prepare, consider, check or dispose. */ @@ -103,6 +108,9 @@ struct Method { /*========== general utility functions ==========*/ +static UnkMap unkfeatbit(int featix) { return (UnkMap)1 << featix; } +static UnkMap unkallfeatbits(int nfeats) { return ~(~(UnkMap)0 << nfeats); } + const char *movpos_pname(const Segment *move, MovPosComb poscomb) { return !SOMEP(poscomb) ? "?" : move->i->poscombs[poscomb].pname; } @@ -110,22 +118,32 @@ const char *movpos_pname(const Segment *move, MovPosComb poscomb) { static void ouposn_moving(const MovPosChange *indep) { Segment *move= indep->move; ouprintf("movpos %s position %s moving\n", - move->i->pname, movpos_pname(move, indep->actual)); + move->i->pname, + indep->actualunk ? "?" : movpos_pname(move, indep->actualpos)); +} +static void ouposn_stable(const Segment *move) { + ouprintf("movpos %s position %s stable\n", + move->i->pname, movpos_pname(move, move->movposcomb)); +} +static void ouposn_feat(const Segment *move, const MovFeatInfo *feati, + MovPosComb posn, const Method *m) { + ouprintf("movpos %s feat %s %d %s\n", move->i->pname, + feati->pname, posn, m->pname); +} + +int movposcomb_feature_posn(const MovFeatInfo *feati, MovPosComb comb) { + /* Returns position of individual feature. */ + return (comb / feati->weight) % feati->posns; } -MovPosComb movposcomb_update_feature(MovPosComb startpoint, - const MovFeatInfo *mfi, - int featpos) { +MovPosComb movposcomb_feature_update(const MovFeatInfo *mfi, + MovPosComb startpoint, int featpos) { MovPosComb above_weight= mfi->weight * mfi->posns; MovPosComb above= startpoint / above_weight; MovPosComb below= startpoint % mfi->weight; return above*above_weight + featpos*mfi->weight + below; } -MovPosComb movpos_poscomb_actual(const Segment *seg) { - return seg->moving ? seg->motion->actual : seg->movposcomb; -} - static void ignore_all_abandon(Method *m) { } /*========== points and other fixed timeslot movfeats ==========*/ @@ -604,7 +622,6 @@ typedef struct NomoveChange { typedef struct { Method m; - unsigned eventqueued:1; NomoveChange *queuehead; /* contains confirmations only */ } NomoveMethod; @@ -646,10 +663,8 @@ static void nomove_remove(Method *mm, Change *remvchg) { static ErrorCode nomove_check(Method *mm) { return 0; } -static void *nomove_execute_now(oop_source *source, struct timeval tv, - void *meth_v) { - NomoveMethod *meth= meth_v; - meth->eventqueued= 0; +static void nomove_execute(Method *mm) { + NomoveMethod *meth= (void*)mm; NomoveChange *done; while ((done= meth->queuehead)) { @@ -661,15 +676,6 @@ static void *nomove_execute_now(oop_source *source, struct timeval tv, DLIST1_REMOVE(meth->queuehead, done, inqueue); nomove_dispose(&meth->m, &done->h); } - return OOP_CONTINUE; -} - -static void nomove_execute(Method *mm) { - NomoveMethod *meth= (void*)mm; - if (!meth->eventqueued) { - meth->eventqueued= 1; - events->on_time(events, OOP_TIME_NOW, nomove_execute_now, meth); - } } static Method nomove_method= { @@ -705,11 +711,12 @@ static Method *methods[]= { static void method_update_feature(Method *m, MovPosChange *indep, const Motion *mo) { - ouprintf("movpos %s feat %s %d %s\n", indep->move->i->pname, - mo->i->pname, mo->posn, m->pname); - if (SOMEP(indep->actual)) - indep->actual= - movposcomb_update_feature(indep->actual, mo->i, mo->posn); + int featix= mo->i - indep->move->i->movfeats; + assert(featix >= 0 && featix < indep->move->i->n_movfeats); + ouposn_feat(indep->move, mo->i, mo->posn, m); + indep->actualpos= + movposcomb_feature_update(mo->i, indep->actualpos, mo->posn); + indep->actualunk &= ~unkfeatbit(featix); ouposn_moving(indep); } @@ -731,7 +738,8 @@ static void method_change_done(Method *m, Change *chg) { return; } - indep_indep_done(indep); + if (!indep->refcount) + indep_indep_done(indep); } static void indep_indep_done(Indep *indep) { @@ -740,8 +748,7 @@ static void indep_indep_done(Indep *indep) { move->moving= 0; move->motion= 0; move->movposcomb= indep->target; - ouprintf("movpos %s position %s stable\n", - move->i->pname, movpos_pname(move, move->movposcomb)); + ouposn_stable(move); free(indep); } @@ -755,17 +762,20 @@ static Method *feature_method(const MovFeatInfo *feati) { return meth; } -static int change_needed(const MovFeatInfo *feati, - MovPosComb startpoint, MovPosComb target) { +static int change_needed(int featix, const MovFeatInfo *feati, + MovPosComb startpointpos, UnkMap startpointunk, + MovPosComb target) { int r; - r= !SOMEP(startpoint) || + + r= (startpointunk & unkfeatbit(featix)) || (target / feati->weight) % feati->posns - - (startpoint / feati->weight) % feati->posns; + (startpointpos / feati->weight) % feati->posns; + if (DEBUGP(movpos,eval)) DPRINTFA(" { %s:%s(%d*%d) %d..%d => %d }", feature_method(feati)->pname, feati->pname, feati->posns, feati->weight, - startpoint, target, r); + startpointpos, target, r); return r; } @@ -792,7 +802,7 @@ static void indep_dispose(MovPosChange *indep) { #define EVAL_MAX_MOTIONS 2 static ErrorCode indep_prepare(Segment *move, MovPosComb target, - MovPosComb startpoint, + MovPosComb startpointpos, int ms, int confirming, MovPosChange **indep_r /* 0 ok */, int *cost_r /* 0 ok */) { @@ -803,22 +813,47 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target, const SegmentInfo *movei= move->i; int feat, DP; + UnkMap startpointunk; MovPosChange *indep=0; DPRINTF1(movpos,eval, "movpos prepare %s/%s <-%s", move->i->pname, - movpos_pname(move,target), movpos_pname(move,startpoint)); + movpos_pname(move,target), movpos_pname(move,startpointpos)); - if (!SOMEP(startpoint)) { - startpoint= movpos_poscomb_actual(move); - DPRINTF2(" actual <-%s", movpos_pname(move,startpoint)); + if (SOMEP(startpointpos)) { + startpointunk= 0; + } else { + if (move->moving) { + startpointpos= move->motion->actualpos; + startpointunk= move->motion->actualunk; + } else if (SOMEP(move->movposcomb)) { + startpointpos= move->movposcomb; + startpointunk= 0; + } else { + startpointpos= 0; + startpointunk= unkallfeatbits(move->i->n_movfeats); + } + if (DP) { + DPRINTF2(" actual <-%s/", move->i->pname); + for (feat=0; featn_movfeats; feat++) { + const MovFeatInfo *feati= &movei->movfeats[feat]; + if (startpointunk & unkfeatbit(feat)) + DPRINTF2("%s?", feati->pname); + else + DPRINTF2("%s%d", feati->pname, + startpointpos / feati->weight % feati->posns); + } + } } n_meths= 0; for (feat=0; featn_movfeats; feat++) { const MovFeatInfo *feati= &movei->movfeats[feat]; - if (!change_needed(feati,startpoint,target)) continue; + if (!change_needed(feat,feati, + startpointpos,startpointunk, + target)) + continue; MovPosComb posn= target / feati->weight % feati->posns; Method *meth= feature_method(feati); @@ -850,9 +885,11 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target, DPRINTF2(" alloc"); indep= mmalloc(sizeof(*indep) + sizeof(Change*) * n_meths); indep->move= move; - indep->actual= startpoint; + indep->actualpos= startpointpos; + indep->actualunk= startpointunk; indep->target= target; indep->n_changes= n_meths; + indep->refcount= 0; memset(indep->changes, 0, sizeof(Change*) * n_meths); } DPRINTF2("\n"); @@ -1072,19 +1109,10 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd, ErrorCode movpos_change(Segment *move, MovPosComb target, int maxdelay_ms, MovPosChange *resv) { int DP; - MovPosComb actual; ErrorCode ec; - if (!move->moving) { - actual= move->movposcomb; - assert(!move->motion); - } else { - actual= move->motion->actual; - } - - DPRINTF1(movpos,entry, "movpos change %s/%s maxdelay=%dms actual=%s", - move->i->pname, movpos_pname(move, target), - maxdelay_ms, movpos_pname(move, actual)); + DPRINTF1(movpos,entry, "movpos change %s/%s maxdelay=%dms", + move->i->pname, movpos_pname(move, target), maxdelay_ms); if (resv) DPRINTF2(" resv=%s/%s", resv->move->i->pname, movpos_pname(resv->move, resv->target)); @@ -1094,7 +1122,7 @@ ErrorCode movpos_change(Segment *move, MovPosComb target, MovPosChange *inst= 0; - ec= indep_prepare(move,target, actual, + ec= indep_prepare(move,target, NOTA(MovPosComb), maxdelay_ms,1, &inst, 0); if (ec) goto x; @@ -1111,9 +1139,12 @@ ErrorCode movpos_change(Segment *move, MovPosComb target, move->motion= inst; move->moving= 1; + inst->refcount++; /* prevents method_change_done from destroying it */ + ouposn_moving(inst); indep_check_execute(); + inst->refcount--; if (!inst->n_changes) /* oh! */ indep_indep_done(inst); @@ -1156,11 +1187,29 @@ void motions_all_abandon(void) { MovPosChange *abandon= seg->motion; indep_remove(abandon); - indep_dispose(abandon); - seg->movposcomb= abandon->actual; + seg->movposcomb= abandon->actualunk ? NOTA(MovPosComb) : abandon->actualpos; seg->moving= 0; seg->motion= 0; + indep_dispose(abandon); } for (meth=methods; *meth; meth++) (*meth)->all_abandon(*meth); } + +void movpos_reportall(void) { + SEG_IV; + int feat; + + FOR_SEG { + assert(!seg->moving); + if (seg->i->n_poscombs <= 1) continue; + ouposn_stable(seg); + if (SOMEP(seg->movposcomb)) { + for (feat=0; feati->n_movfeats; feat++) { + const MovFeatInfo *feati= &seg->i->movfeats[feat]; + MovPosComb posn= (seg->movposcomb / feati->weight) % feati->posns; + ouposn_feat(seg, feati, posn, feature_method(feati)); + } + } + } +}