chiark / gitweb /
realtime: break out new function movpos.c:ouposn_feat
[trains.git] / hostside / movpos.c
index 9c0cc7597c1be5167f4f7685206faa2c7721511e..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);
 }
 
@@ -846,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");
@@ -1104,9 +1109,16 @@ 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);
+
   DPRINTF(movpos,entry, "movpos change %s/%s ok\n",
          move->i->pname, movpos_pname(move, target));
   return 0;
@@ -1145,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);