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;
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;
}
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 ==========*/
/* 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 */
* 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
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) {
struct MovPosChange {
Segment *move;
- MovPosComb start;
- MovPosComb actual;
+ MovPosComb actual, target;
int n_changes;
Change *changes[];
};
-
+
static Method *methods[]= {
&nomove_method,
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;
/* 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];
if (!SOMEP(startpoint)) {
startpoint= movpos_poscomb_actual(move);
- fixme actual plumbing etc;
DPRINTF(movpos,eval, " actual <-%s\n",
movpos_pname(move,startpoint));
}
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");
}
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;
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*/) {
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;
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;
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 */
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) {