chiark / gitweb /
safety: movpos: new function movposcomb_feature_posn
[trains.git] / hostside / movpos.c
index e919f4729c9fdea93e86a02887f688bfcb24907e..75a139d93b73e7cfdac8615ea96ecea8631a5386 100644 (file)
@@ -14,10 +14,15 @@ typedef struct {
 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;
@@ -35,9 +40,9 @@ static void method_change_done(Method *m, Change *chg);
    * 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.
    */
 
 
@@ -103,6 +108,9 @@ struct Method {
 
 /*========== 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;
 }
@@ -110,22 +118,32 @@ const char *movpos_pname(const Segment *move, MovPosComb poscomb) {
 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 ==========*/
@@ -604,7 +622,6 @@ typedef struct NomoveChange {
 
 typedef struct {
   Method m;
-  unsigned eventqueued:1;
   NomoveChange *queuehead; /* contains confirmations only */
 } NomoveMethod;
 
@@ -646,10 +663,8 @@ static void nomove_remove(Method *mm, Change *remvchg) {
 
 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)) {
@@ -661,15 +676,6 @@ static void *nomove_execute_now(oop_source *source, struct timeval tv,
     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= {
@@ -705,11 +711,12 @@ static Method *methods[]= {
 
 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);
 }
 
@@ -731,7 +738,8 @@ static void method_change_done(Method *m, Change *chg) {
     return;
   }
 
-  indep_indep_done(indep);
+  if (!indep->refcount)
+    indep_indep_done(indep);
 }
 
 static void indep_indep_done(Indep *indep) {
@@ -740,8 +748,7 @@ 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);
 }
 
@@ -755,17 +762,20 @@ static Method *feature_method(const MovFeatInfo *feati) {
   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;
 }
 
@@ -792,7 +802,7 @@ static void indep_dispose(MovPosChange *indep) {
 #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 */) {
@@ -803,22 +813,47 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target,
 
   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);
 
@@ -850,9 +885,11 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target,
     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");
@@ -1072,19 +1109,10 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd,
 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));
@@ -1094,7 +1122,7 @@ ErrorCode movpos_change(Segment *move, MovPosComb 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;
@@ -1111,9 +1139,12 @@ ErrorCode movpos_change(Segment *move, MovPosComb target,
   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);
@@ -1156,11 +1187,29 @@ void motions_all_abandon(void) {
 
     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));
+      }
+    }
+  }
+}