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;
* 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.
*/
/*========== 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;
}
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 ==========*/
typedef struct {
Method m;
- unsigned eventqueued:1;
NomoveChange *queuehead; /* contains confirmations only */
} NomoveMethod;
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)) {
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= {
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);
}
return;
}
- indep_indep_done(indep);
+ if (!indep->refcount)
+ indep_indep_done(indep);
}
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);
}
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;
}
#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 */) {
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; feat<movei->n_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; feat<movei->n_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);
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");
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));
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;
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);
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; feat<seg->i->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));
+ }
+ }
+ }
+}