chiark / gitweb /
movpos: wip multiple movfeatkinds in one request; before abolish indep_prepare
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Tue, 28 Dec 2010 21:48:51 +0000 (21:48 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sat, 8 Jan 2011 22:44:47 +0000 (22:44 +0000)
hostside/movpos.c
hostside/safety.h

index 845cee05aebfadf8a87fb95f46eb17b03f243544..d6692864f5fc97b270f1c1237d5b109e8c9a0cf1 100644 (file)
@@ -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) {
index 2e4fc85201de66105db32bbf1533e3bcc56e1dac..ba32a9dbb2ab9fbd2c07928b6d9e67a93d11af05 100644 (file)
@@ -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: