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
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 */
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) {
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, \
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;
feat<movei->n_movfeats;
feat++, feati++) {
if (!change_needed(feati,startpoint,target)) continue;
- for (i=0; i<n_changes; i++)
-
+ MovPosComb posn= target / feati->weight % feati->posns;
+ Method *meth= methods[kind];
+
+ int methi;
+ for (methi=0; methi<n_meths; methi++)
+ if (meths[methi] == meth) goto found_method;
+ /* need a new method */
+ methi= ++n_meths;
+ if (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; changei<n_meths; changei++) {
+ Method *meth= meths[changei];
+ int thiscost= 0;
+ ec= meth->prepare(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; ii<inst->n_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; jj<remv->n_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; ii<inst->n_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; changei<indep->n_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;
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;
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;
int n_motions=0;
Motion motions[movei->n_movfeats];
- for (feat=0, feati=movei->movfeats;
- feat<movei->n_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];
*
* 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;
+}
+