chiark / gitweb /
realtime: break out new function movpos.c:ouposn_feat
[trains.git] / hostside / movpos.c
index 541d273b951196411508be845f92e2a6dced12eb..b13326761792cb50868b7ebb44cdab775948ed25 100644 (file)
@@ -18,6 +18,7 @@ typedef struct MovPosChange {
   Segment *move;
   /* everything beyond here is private for indep */
   MovPosComb actual, target;
+  int refcount;
   int n_changes;
   Change *changes[];
 } Indep;
@@ -35,9 +36,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.
    */
 
 
@@ -112,6 +113,15 @@ static void ouposn_moving(const MovPosChange *indep) {
   ouprintf("movpos %s position %s moving\n",
           move->i->pname, movpos_pname(move, indep->actual));
 }
+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);
+}
 
 MovPosComb movposcomb_update_feature(MovPosComb startpoint,
                                     const MovFeatInfo *mfi,
@@ -604,7 +614,6 @@ typedef struct NomoveChange {
 
 typedef struct {
   Method m;
-  unsigned eventqueued:1;
   NomoveChange *queuehead; /* contains confirmations only */
 } NomoveMethod;
 
@@ -646,10 +655,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 +668,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= {
@@ -692,18 +690,20 @@ static Method nomove_method= {
 #define METH_DPFX_FMT "%s " INDEP_DBG_FMT " "
 #define METH_DPFX_ARGS(indep, meth) ((meth).pname), INDEP_DBG_ARGS((indep))
 
+static void indep_indep_done(Indep *indep);
+
 static Method *methods[]= {
   [mfk_none] = (Method*)&nomove_method,
   [mfk_point] = (Method*)&points_method,
   [mfk_relay] = (Method*)&waggle,
+  0
 };
 
 /*---------- entrypoints from 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);
+  ouposn_feat(indep->move, mo->i, mo->posn, m);
   if (SOMEP(indep->actual))
     indep->actual=
       movposcomb_update_feature(indep->actual, mo->i, mo->posn);
@@ -728,13 +728,17 @@ static void method_change_done(Method *m, Change *chg) {
     return;
   }
 
+  if (!indep->refcount)
+    indep_indep_done(indep);
+}
+
+static void indep_indep_done(Indep *indep) {
   /* all done */
   Segment *move= indep->move;
   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);
 }
 
@@ -752,7 +756,8 @@ static int change_needed(const MovFeatInfo *feati,
                         MovPosComb startpoint, MovPosComb target) {
   int r;
   r= !SOMEP(startpoint) ||
-    (target - startpoint) / feati->weight % feati->posns;
+    (target / feati->weight) % feati->posns -
+    (startpoint / feati->weight) % feati->posns;
   if (DEBUGP(movpos,eval))
     DPRINTFA(" { %s:%s(%d*%d) %d..%d => %d }",
             feature_method(feati)->pname, feati->pname,
@@ -770,12 +775,12 @@ static void indep_dispose(MovPosChange *indep) {
   int changei;
   for (changei=0; changei<indep->n_changes; changei++) {
       Change *chg= indep->changes[changei];
+      if (!chg) continue;
+
       Method *meth= chg->meth;
-      if (chg) {
-       DPRINTF(movpos,meth, METH_DPFX_FMT "dispose...\n",
-               METH_DPFX_ARGS(indep,*meth));
-       meth->dispose(meth, chg);
-      }
+      DPRINTF(movpos,meth, METH_DPFX_FMT "dispose...\n",
+             METH_DPFX_ARGS(indep,*meth));
+      meth->dispose(meth, chg);
   }
   free(indep);
 }
@@ -845,6 +850,7 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target,
     indep->actual= startpoint;
     indep->target= target;
     indep->n_changes= n_meths;
+    indep->refcount= 0;
     memset(indep->changes, 0, sizeof(Change*) * n_meths);
   }
   DPRINTF2("\n");
@@ -885,10 +891,10 @@ static ErrorCode indep_prepare(Segment *move, MovPosComb target,
   if (cost_r) *cost_r= totalcost;
 
   if (indep_r)
-    DPRINTF(movpos,entry, INDEP_DPFX_FMT "prepare cost=%d ok\n",
+    DPRINTF(movpos,eval, INDEP_DPFX_FMT "prepare cost=%d ok\n",
            INDEP_DPFX_ARGS(indep), totalcost);
   else
-    DPRINTF(movpos,entry, "movpos prepare %s/%s cost=%d ok\n",
+    DPRINTF(movpos,eval, "movpos prepare %s/%s cost=%d ok\n",
            move->i->pname, movpos_pname(move,target), totalcost);
   return 0;
 
@@ -999,6 +1005,7 @@ movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r,
 
   DPRINTF(movpos,entry, "movpos reserve %s/%s ok\n",
          move->i->pname, movpos_pname(move,target));
+  *res_r= indep;
   return 0;
 
  x:
@@ -1018,11 +1025,24 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd,
   int tcost, bestcost=INT_MAX;
   const SegPosCombInfo *pci;
 
+  DPRINTF(movpos,eval, "movpos_findcomb_bysegs %s-%s-%s <-%s\n",
+         back ? back->i->pname : "*", move->i->pname,
+         fwd  ? fwd ->i->pname : "*", movpos_pname(move, startpoint));
+
   for (tcomb=0, pci=movei->poscombs;
        tcomb<movei->n_poscombs;
        tcomb++, pci++) {
+    /* these next assignments may generate segments[-1] but we don't
+     * care because that won't compare equal to back or fwd */
     Segment *tback= &segments[pci->link[1].next];
     Segment *tfwd=  &segments[pci->link[0].next];
+
+    DPRINTF(movpos,intern, "movpos_findcomb_bysegs  ... %s : %s-%s-%s\n",
+           movpos_pname(move, tcomb),
+           SOMEP(pci->link[1].next) ? tback->i->pname : "#",
+           move->i->pname,
+           SOMEP(pci->link[0].next) ? tfwd->i->pname : "#");       
+
     if (back && !(back==tback || back==tfwd)) continue;
     if (fwd  && !(fwd ==tback || fwd ==tfwd)) continue;
 
@@ -1036,6 +1056,11 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd,
     bestcomb= tcomb;
     bestcost= tcost;
   }
+  DPRINTF(movpos,entry, "movpos_findcomb_bysegs %s..%s..%s <-%s => %s/%s\n",
+         back ? back->i->pname : "-", move->i->pname,
+         fwd  ? fwd ->i->pname : "-", movpos_pname(move, startpoint),
+         move->i->pname, movpos_pname(move,bestcomb));
+
   if (chosen_r) *chosen_r= bestcomb;
   return
     bestcost==INT_MAX ? EC_MovFeatRouteNotFound :
@@ -1082,10 +1107,18 @@ ErrorCode movpos_change(Segment *move, MovPosComb target,
   indep_dispose(move->motion);
 
   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);
+
   DPRINTF(movpos,entry, "movpos change %s/%s ok\n",
          move->i->pname, movpos_pname(move, target));
   return 0;
@@ -1124,9 +1157,10 @@ void motions_all_abandon(void) {
 
     MovPosChange *abandon= seg->motion;
     indep_remove(abandon);
-    indep_dispose(abandon);
     seg->movposcomb= abandon->actual;
     seg->moving= 0;
+    seg->motion= 0;
+    indep_dispose(abandon);
   }
   for (meth=methods; *meth; meth++)
     (*meth)->all_abandon(*meth);