From 1533b240ccc28b7498fa34733aeabc9c1230a29f Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 28 Dec 2010 21:48:51 +0000 Subject: [PATCH] movpos: wip multiple movfeatkinds in one request; before abolish indep_prepare --- hostside/movpos.c | 188 +++++++++++++++++++++------------------------- hostside/safety.h | 2 +- 2 files changed, 85 insertions(+), 105 deletions(-) diff --git a/hostside/movpos.c b/hostside/movpos.c index 845cee0..d669286 100644 --- a/hostside/movpos.c +++ b/hostside/movpos.c @@ -47,18 +47,6 @@ struct Change { /* valid in: filled in by and when: */ 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 - * state. It is initialised by indep (just before confirm) from - * move->motion->actual or move->movposcomb as the case may be. It - * should be updated by the kind, since it is used by indep for - * calculating the number and identities of the features which may - * need to change when a new move request is intended to replace an - * existing one - ie, the contents of the motions[] provided to a - * subsequent confirm(). So while a change is Confirmed, the - * physical state is recorded only in the relevant MovPosChange, and not - * in the segment's movposcomb. Once a change goes to Confirmed, - * the indep code never untangles it so the kind can manage the - * proper transition. */ struct Method { const char *pname; @@ -81,6 +69,8 @@ struct Method { void (*all_abandon)(Method *m); /* I */ }; +/*========== general utility functions ==========*/ + const char *movpos_pname(Segment *move, MovPosComb poscomb) { return poscomb<0 ? "?" : move->i->poscombs[poscomb].pname; } @@ -100,6 +90,10 @@ MovPosComb movposcomb_update_feature(MovPosComb startpoint, return above*above_weight + featpos*mfi->weight + below; } +MovPosComb movpos_poscomb_actual(Segment *seg) { + return seg->moving ? seg->motion->actual : seg->movposcomb; +} + static void ignore_all_abandon(Method *m) { } /*========== points and other fixed timeslot movfeats ==========*/ @@ -145,7 +139,6 @@ typedef struct { /* PR QR PC QC */ /* in queue? absent reserved absent confirmed */ Change h; FsqSlot deadline; /* relative relative absolute absolute */ - MovPosComb actual; /* undef undef see below */ int n_motions; /* 1 1 alloc'd num undone */ Motion motions[]; /* [0].i: 0 0 non-0 non-0 */ @@ -160,21 +153,6 @@ typedef struct { /* PR QR PC QC */ * A? to mean statedet says Allocated, but may be queued * etc. They are only allowed while we are in a fsq_... method function. */ - /* FsqReq.actual is subtly differnet to MovPosChange.actual, - * as follows: - * in MovPosChange in FsqReq - * Position unknown -1 0 - * Position partly known -1 unknown feats are 0 - * Position completely known exact exact - * - * The partial knowledge positions can only occur in requests that - * are confirmed with as many motions as features, so we know that - * if we complete a request we know that we can copy actual out - * to MovPosChange. - * - * If we abandon a half-done change to a multi-feat segment - * we lose the partial knowledge. - */ #define FSQ_MAX_QUEUE 15 @@ -425,7 +403,7 @@ static void fsq_check_action(FsqMethod *m) { m->f.move(m, mo->i, mo->posn); m->f.cslot++; - indep_update_feature(&m->m, r->h.indep, mo); + method_update_feature(&m->m, r->h.indep, mo); } if (!r->n_motions) { @@ -642,12 +620,11 @@ static Method nomove_method= { struct MovPosChange { Segment *move; - MovPosComb start; - MovPosComb actual; + MovPosComb actual, target; int n_changes; Change *changes[]; }; - + static Method *methods[]= { &nomove_method, @@ -656,16 +633,32 @@ static Method *methods[]= { 0 }; -static void indep_update_feature(Method *m, MovPosChange *indep, +/*---------- entrypoints from methods ----------*/ + +static void method_update_feature(Method *m, MovPosChange *indep, const Motion *mo) { - if (SOMEP(indep->start)) - ouprintf("movpos %s feat %s %d %s\n", indep->move->i->pname, - mo->i->pname, mo->posn, m.pname); - indep->actual= - movposcomb_update_feature(indep->actual, mo->i, mo->posn); + /* Called from methods' execution logic when an individual feature + * has been moved. This is used by the method-independent code to + * compute the correct delta set of movements from the current + * actual position, when thinking about new plans. It is also sent + * to clients and ultimately used by the UI. + */ + 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); } -static void indep_change_done(Method *m, Change *chg) { +static void method_change_done(Method *m, Change *chg) { + /* Called from methods' execution logic when a whole change + * 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). + */ MovPosComb *indep= chg->indep; Change **search; @@ -683,20 +676,34 @@ static void indep_change_done(Method *m, Change *chg) { /* all done */ move->moving= 0; move->motion= 0; - move->movposcomb= indep->actual; + move->movposcomb= indep->target; ouprintf("movpos %s position %s stable\n", move->i->pname, movpos_pname(move, move->movposcomb)); free(indep); } +/*---------- internal core machinery ----------*/ + +static int change_needed(const MovFeatInfo *feati, + MovPosComb startpoint, MovPosComb target) { + int r; + r= !SOMEP(startpoint) || + (target - startpoint) / feati->weight % feati->posns; + DPRINTF(movpos,changeneeded, "%s:%s(%d*%d) %d..%d => %d\n", + methods[feati->kind]->pname, feati->pname, + feati->posns, feati->weight, + startpoint, target, r); + return r; +} + #define EVAL_MAX_METHODS 2 #define EVAL_MAX_MOTIONS 2 -static ErrorCode evaluate_target(Segment *move, MovPosComb target, - MovPosComb startpoint, - int ms, int confirming, - MovPosChange *indep_r /* 0 ok */, - int *cost_r /* 0 ok */) { +static ErrorCode indep_prepare(Segment *move, MovPosComb target, + MovPosComb startpoint, + 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]; @@ -713,7 +720,6 @@ static ErrorCode evaluate_target(Segment *move, MovPosComb target, if (!SOMEP(startpoint)) { startpoint= movpos_poscomb_actual(move); - fixme actual plumbing etc; DPRINTF(movpos,eval, " actual <-%s\n", movpos_pname(move,startpoint)); } @@ -751,8 +757,8 @@ static ErrorCode evaluate_target(Segment *move, MovPosComb target, 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; + indep->start= startpoint; + indep->target= target; } DPRINTF(movpos,eval, "\n"); @@ -789,8 +795,9 @@ static ErrorCode evaluate_target(Segment *move, MovPosComb target, } static ErrorCode -indep_swap(MovPosChange *remv, MovPosChange *inst) { - /* does consider and check */ +indep_consider(MovPosChange *remv, MovPosChange *inst) { + /* does consider and check; on failure, it does consider on remv + * and check (which is guaranteed to always succeed) */ assert(inst->n_changes <= 32); assert(remv->n_changes <= 32); uint32_t inst_done, remv_done; @@ -862,6 +869,8 @@ static void indep_dispose(MovPosChange *indep) { free(indep); } +/*---------- entrypoints from rest of program ----------*/ + ErrorCode movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r, MovPosComb target, MovPosComb startpoint /*as for findcomb*/) { @@ -872,8 +881,8 @@ movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r, move->i->pname, movpos_pname(move,target), maxdelay_ms, movpos_pname(move,startpoint)); - ec= evaluate_target(move,target, startpoint, - ms,1, + ec= indep_prepare(move,target, startpoint, + ms,0, &indep, 0); if (ec) return ec; @@ -889,18 +898,6 @@ movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r, return ec; } -static int change_needed(const MovFeatInfo *feati, - MovPosComb startpoint, MovPosComb target) { - int r; - r= startpoint<0 || - (target - startpoint) / feati->weight % feati->posns; - DPRINTF(movpos,changeneeded, "%s:%s(%d*%d) %d..%d => %d\n", - methods[feati->kind]->pname, feati->pname, - feati->posns, feati->weight, - startpoint, target, r); - return r; -} - ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd, MovPosComb startpoint, MovPosComb *chosen_r) { const SegmentInfo *movei= move->i; @@ -917,7 +914,7 @@ 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 */ - ec= evaluate_target(move,tcomb,startpoint, -1,0, 0,&tcost); + ec= indep_prepare(move,tcomb,startpoint, -1,0, 0,&tcost); if (ec) return ec; if (tcost >= bestcost) /* prefer low-numbered movposcombs */ @@ -932,78 +929,61 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd, 0; } - -NEW CODE UP TO HERE - ErrorCode movpos_change(Segment *move, MovPosComb target, - int maxdelay_ms, MovPosChange *chg) { + int maxdelay_ms, MovPosChange *resv) { const SegmentInfo *movei= move->i; const MovFeatInfo *feati; int feat; MovPosComb actual; ErrorCode ec; - MovFeatKind kind= mfk_none; if (!move->moving) { actual= move->movposcomb; assert(!move->motion); } else { - kind= move->motion->meth->kind; actual= move->motion->actual; } DPRINTF(movpos,change, "%s/%s maxdelay=%dms actual=%s\n", move->i->pname, movpos_pname(move,target), maxdelay_ms, movpos_pname(move, actual)); - if (chg) DPRINTF(movpos,change, " chg=%s:%s/%s\n", - chg->meth->pname, chg->move->i->pname, - movpos_pname(chg->move, chg->intent)); - - { /* provide horizon for visibility of motions[] */ - int n_motions=0; - Motion motions[movei->n_movfeats]; + if (resv) DPRINTF(movpos,change, " chg=%s:%s/%s\n", + chg->meth->pname, chg->move->i->pname, + movpos_pname(chg->move, chg->intent)); - there was code here to fill in motions + MovPosChange *indep= 0; - Method *meth= methods[kind]; + ec= indep_prepare(move,target, actual, + maxdelay_ms,1, + &indep, 0); + if (ec) goto x; - if (chg) { - if (chg->meth != meth || - chg->move != move || - chg->intent != target) - return EC_MovFeatReservationInapplicable; - } else { - chg= mp_allocate(meth,move,n_motions,target); - } - chg->actual= actual; + ec= indep_consider(resv, indep); + if (ec) goto x; - DPRINTF(movpos,change, "confirm %s:%d...\n", - meth->pname, n_motions); - ec= meth->confirm(meth, chg, move, n_motions, motions, maxdelay_ms); - DPRINTF(movpos,change, "confirm => %s\n",errorcodelist[ec]); - if (ec) goto x; - } + indep_dispose(resv); + indep_execute(); return 0; x: - movpos_unreserve(chg); + indep_dispose(indep); + indep_execute(); return ec; } -void movpos_unreserve(MovPosChange *res) { +void movpos_unreserve(MovPosChange *resv) { if (!res) return; DPRINTF(movpos,unreserve, "%s:%s/%s\n", res->meth->pname, res->move->i->pname, movpos_pname(res->move, res->intent)); - res->meth->destroy(res->meth, res); -} - -MovPosComb movpos_poscomb_actual(Segment *seg) { - return seg->moving ? seg->motion->actual : seg->movposcomb; + ErrorCode ec= indep_consider(resv, 0); + assert(!ec); + indep_dispose(resv); + indep_execute(); } -MovPosComb movpos_change_intent(MovPosChange *chg) { - return chg->intent; +MovPosComb movpos_change_intent(MovPosChange *indep) { + return indep->intent; } void motions_all_abandon(void) { diff --git a/hostside/safety.h b/hostside/safety.h index 2e4fc85..ba32a9d 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -175,7 +175,7 @@ movpos_change(Segment *tomove, MovPosComb target, * made to replace that change with the new request; if this is not * successful then the existing change will still happen. * - * reservation should be 0, or the results of movpos_reservechange + * reservation should be 0, or the results of movpos_reserve * on the same move. It is always consumed, even on error. * * One of the following must be true of tomove on entry: -- 2.30.2