/*========== declarations ==========*/
typedef struct {
- MoveFeatInfo *i;
+ const MovFeatInfo *i;
Small posn;
} Motion;
* C Confirmed motion queued and will occur
* D Done motion is complete and callback just needs to be made
* E Erroneous indep must call destroy straight away
- * seg->moving is in one of the states UCD
+ * seg->moving is in one of the states UC
*/
typedef struct MovPosChange { /* valid in: filled in by and when: */
const KindInfo *ki; /* ARCDE indep after allocate() */
Segment *move; /* ARCDE indep after allocate() */
- MovPosCallback *on_done; /* CD indep before confirm() */
- void *u; /* CD indep before confirm() */
MovPosComb actual; /* CD see below */
/* kind-specific data follows */ /* varies kind-specific code, varies */
} Change;
* Allocated Allocated yes
* Reserved Reserved yes
* Confirmed Confirmed yes
- * Done Allocated yes
* Erroneous A/R/C no
*
* Erroneous exists only after a failed reserve() or confirm() so it's
typedef struct { /* Allocated Reserved Confirmed */
/* in queue? absent reserved confirmed */
- ChangeHeader h;
- Slot deadline; /* ~0 relative absolute <- */
+ Change h;
+ PtSlot deadline; /* ~0 relative absolute <- */
int n_motions; /* alloc'd alloc'd undone */
Motion motions[]; /* [0].i: 0 0 non-0 <- */
/* [..].i: undef undef non-0 */
#define CDU_RECHARGE 250 /*ms*/
#define POINT_MOVEMENT 50 /*ms*/
+#define PT_MAX_QUEUE 15
typedef struct {
int n;
PointReq *l[PT_MAX_QUEUE];
} PointQueue;
-todo
- actually fire points: use item, and remove it, etc.
- write check routine
-
-#define PT_MAX_QUEUE 15
-
/*
* CDU and point queue states:
*
static int pt_cdu_charged;
static PointQueue pt_confirmed, pt_reserved;
-static pt_maxdelay_reldeadline(int maxdelay_ms) {
+static void pt_check_action(void);
+
+static PtSlot pt_maxdelay_reldeadline(int maxdelay_ms) {
return (maxdelay_ms - POINT_MOVEMENT + CDU_RECHARGE) / CDU_RECHARGE;
}
memmove(&q->l[index], &q->l[index+1], sizeof(q->l[0]) * (q->n - index));
}
-static void pt_req_compar(const void *av, const void *bv) {
- PointQueue *const *a= av;
- PointQueue *const *b= av;
+static int pt_req_compar(const void *av, const void *bv) {
+ PointReq *const *a= av;
+ PointReq *const *b= av;
return (PtSlotSigned)((*b)->deadline - (*a)->deadline);
}
static void pt_queue_remove_item(PointQueue *q, PointReq *r) {
- PointQueue **entry;
+ PointReq **entry;
entry= bsearch(r, q->l, q->n, sizeof(q->l[0]), pt_req_compar);
assert(entry);
pt_queue_remove_index(q, entry - q->l);
static ErrorCode pt_check_plan(void) {
/* Checks whether we can meet the currently queued commitments */
- int future, conf, resv;
+ int future, conf, resv, usewhen;
conf=resv=0;
/* If CDU is charged we can do one thing right away */
while (conf < pt_confirmed.n &&
- pt_confirmed.l[0].deadline==pt_cslot) {
- if (!pt_cdu_charged) return EC_Points;
- if (conf) return EC_Points;
+ pt_confirmed.l[0]->deadline==pt_cslot) {
+ if (!pt_cdu_charged) return EC_MovFeatTooLate;
+ if (conf) return EC_MovFeatTooLate;
conf++;
}
usewhen= confwhen;
conf++;
}
- if (usewhen > future) return EC_Points;
+ if (usewhen > future) return EC_MovFeatTooLate;
future++;
}
return 0;
}
static ErrorCode pt_enqueue(PointQueue *q, PointReq *r) { /* XA -> X */
- ErrorCode ec; /* ... where X is R or C and corresponds to q */
+ int insat; /* ... where X is R or C and corresponds to q */
/* or on error, XA -> A */
if (q->n == PT_MAX_QUEUE) {
}
for (insat= q->n;
- insat>0 && CLOCK_COMPARE(r->deadline, <, q->l[insat-1]->deadline);
+ insat>0 && (PtSlotSigned)(r->deadline - q->l[insat-1]->deadline) < 0;
insat--)
q->l[insat]= q->l[insat-1];
q->l[insat]= r;
q->n++;
- return pt_check();
+ return pt_check_plan();
/* if this fails, indep machinery calls pt_destroy which dequeues */
}
/*---------- kind method entrypoints ----------*/
-static SomeChange pt_allocate(int alloc_motions) {
- PointReq= *r;
+static Change *point_allocate(int alloc_motions) {
+ PointReq *r;
assert(pt_cdu_charged>=0);
if (!alloc_motions)
r->deadline= ~(PtSlot)0;
r->n_motions= alloc_motions;
r->motions[0].i= 0;
- return (SomeChange*)r;
+ return (Change*)r;
}
-static ErrorCode point_reserve(SomeChange *chg, Segment *move,
+static ErrorCode point_reserve(Change *chg, Segment *move,
int maxdelay_ms) {
PointReq *r= (PointReq*)chg;
- r->deadline= pt_reldeadline(maxdelay_ms);
- if (!r->deadline) { pt_mark_as_allocated(r); return EC_Points; }
- return pt_queue_add(&pt_reserved, r);
+ r->deadline= pt_maxdelay_reldeadline(maxdelay_ms);
+ if (!r->deadline) { pt_mark_as_allocated(r); return EC_MovFeatTooLate; }
+ return pt_enqueue(&pt_reserved, r);
}
-static ErrorCode point_confirm(SomeChange *chg, Segment *move,
+static ErrorCode point_confirm(Change *chg, Segment *move,
int n_motions, const Motion *motions,
int maxdelay_ms) {
PointReq *r= (PointReq*)chg;
PtSlot newdeadline;
int allow_failure;
+ ErrorCode ec;
/* If the segment is moving, these motions are already based on the
* actual physical position which is stored in the existing request.
*/
assert(n_motions <= r->n_motions);
- newdeadline= pt_reldeadline(maxdelay_ms) + cslot;
+ newdeadline= pt_maxdelay_reldeadline(maxdelay_ms) + pt_cslot;
allow_failure= newdeadline < r->deadline;
/* state A or R */
pt_dequeue(r);
- /* states of existing: */
- PointReq *existing= move->moving; /* U or C */
- if (existing) pt_dequeue(existing); /* U or CA */
+ /* states of existing: */
+ PointReq *existing= (PointReq*)move->moving; /* U or C */
+ if (existing) pt_dequeue(existing); /* U or CA */
/* state A or RA */
memcpy(r->motions, motions, sizeof(r->motions[0])*n_motions);
- if (!n_motions) motions[0].i= move->i->movfeats;
- assert(motions[0].i);
+ if (!n_motions) r->motions[0].i= move->i->movfeats;
+ assert(r->motions[0].i);
r->n_motions= n_motions;
r->deadline= newdeadline + pt_cslot;
ec= pt_enqueue(&pt_confirmed, r);
assert(allow_failure || !ec);
- if (existing) { /* CA */
+ if (existing) { /* CA */
if (ec) { /* state C but bad */
pt_dequeue(r); /* state CA */
pt_mark_as_allocated(r); /* state A */
ErrorCode ec_putback= pt_enqueue(&pt_confirmed, existing);
- assert(!ec_putback); /* C */
+ assert(!ec_putback); /* C */
} else { /* state C and good */
- free(existing); /* U */
+ free(existing); /* U */
}
}
- /* either ec=0 state C U
- * or ec!=0 state A C
- * or ec!=0 state C but bad C
+ /* either ec=0 state C U
+ * or ec!=0 state A C
+ * or ec!=0 state C but bad C
*/
if (!ec) pt_check_action();
return ec;
}
-static void pt_destroy(Change *chg) { /* X->XA and then free it */
+static void point_destroy(Change *chg) { /* X->XA and then free it */
PointReq *r= (PointReq*)chg;
pt_dequeue(r);
free(r);
pt_cdu_charged= 0;
MovPosComb above_weight= m->i->weight * m->i->posns;
- MovPosComb above= r->actual / above_weight;
- MovPosComb below= r->actual % m->i->weight;
- r->actual= above*above_weight + m->posn*m->i->weight + below;
+ MovPosComb above= r->h.actual / above_weight;
+ MovPosComb below= r->h.actual % m->i->weight;
+ r->h.actual= above*above_weight + m->posn*m->i->weight + below;
}
if (!r->n_motions) {
* eg if we are asked to move the
*/
Segment *move= r->h.move;
- assert(move->moving == r);
+ assert(move->moving == (Change*)r);
pt_queue_remove_index(&pt_confirmed,0);
pt_mark_as_allocated(r); /* now state A aka Done */
- movpos_done((Change*)r);
+ move->movposcomb= r->h.actual;
+ move->moving= 0;
+ free(r);
pt_check_action();
}
}
/*---------- entrypoints from rest of program ----------*/
-static void points_all_abandon(void) {
+void points_all_abandon(void) {
int i;
assert(!pt_reserved.n);
for (i=0; i<pt_confirmed.n; i++) {
PointReq *r= pt_confirmed.l[i];
Segment *move= r->h.move;
- assert(move->moving == (PointReq*)r);
+ assert(move->moving == (Change*)r);
move->moving= 0;
move->movposcomb= r->h.actual;
free(r);
}
pt_confirmed.n= 0;
pt_cdu_charged= -1;
- toev_stop(&pt_motion_timeout);
}
-static void points_turning_on(void) {
+void points_turning_on(void) {
pt_cdu_charged= 0;
- pt_motion_timeout.duration= POINT_MOVEMENT;
- pt_motion_timeout.callback= pt_motion_done;
- assert(!pt_motion_timeout.running);
}
void on_pic_charged(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
if (pt_cdu_charged<0) return;
pt_cdu_charged= 1;
- if (pt_motion_timeout.running) {
- toev_stop(&pt_motion_timeout);
- pt_motion_done(0);
- }
pt_check_action();
}
+/*========== dummy `nomove' kind ==========*/
+
+static Change *nomove_allocate(int alloc_motions) {
+ return mmalloc(sizeof(Change));
+}
+static void nomove_destroy(Change *chg) { free(chg); }
+
+static ErrorCode nomove_reserve(Change *chg, Segment *move, int ms) {
+ return 0;
+}
+static ErrorCode nomove_confirm(Change *chg, Segment *move, int n_motions,
+ const Motion *motions, int ms) {
+ nomove_destroy(chg);
+ return 0;
+}
+
/*========== method-independent machinery ==========*/
static const KindInfo methodinfos[]= {
- { nomove_allocate, nomove_reserve, nomove_request, nomove_cancel },
- { point_allocate, point_reserve, point_request, point_cancel },
- 0
+ { nomove_allocate, nomove_reserve, nomove_confirm, nomove_destroy },
+ { point_allocate, point_reserve, point_confirm, point_destroy },
+ { 0 }
};
-static void movpos_done(Change *chg) {
- Segment *move= chg->move;
- events_
- move->movposcomb= r->actual;
- move->moving= 0;
- r->h.on_done(move, r->h.u);
- free(r);
-}
-
-ChangeHeader *mp_allocate(const KindInfo *ki, Segment *move,
- int alloc_motions) {
+static Change *mp_allocate(const KindInfo *ki, Segment *move,
+ int alloc_motions) {
assert(sta_state >= Sta_Resolving);
- chg= (ChangeHeader*)ki->allocate(alloc_motions);
+ Change *chg= ki->allocate(alloc_motions);
chg->ki= ki;
chg->move= move;
return chg;
}
ErrorCode
-movpos_change(Segment *back, Segment *move, *Segment *fwd,
- int maxdelay_ms, MovPosChange chg,
- MovPosCallback *on_done, *u) {
+movpos_change(Segment *back, Segment *move, Segment *fwd,
+ int maxdelay_ms, MovPosChange *chg) {
const SegmentInfo *movei= move->i;
- SegPosCombInfo *pci;
+ const SegPosCombInfo *pci;
+ const MovFeatInfo *feati;
+ int feat;
MovPosComb actual, tcomb, bestcomb=0;
int tchanges, bestchanges=INT_MAX;
ErrorCode ec;
-
MovFeatKind kind= mfk_none;
if (move->moving) {
tcomb++, pci++) {
Segment *tback= &segments[pci->backwards.next];
Segment *tfwd= &segments[pci->forwards .next];
- if (back && !(back==tback || back=tfwd)) continue;
- if (fwd && !(fwd ==tback || fwd =tfwd)) continue;
+ if (back && !(back==tback || back==tfwd)) continue;
+ if (fwd && !(fwd ==tback || fwd ==tfwd)) continue;
if (movei->n_movfeats>1) {
/* we have to search for the one which is least effort, then */
if (bestchanges==INT_MAX) { ec= EC_Invalid; goto x; }
- int n_motions=0;
- Motion motions[movei->n_movfeats];
+ {
+ int n_motions=0;
+ Motion motions[movei->n_movfeats];
- for (feat=0, feati=movei->movfeats;
- feat<movei->n_movfeats;
- feat++, feati++) {
- if ((bestcomb - actual) / feati->weight % feati->posns)
- continue;
- if (kind) {
- if (feati->kind != kind) { ec= EC_MovFeatKindsCombination; goto x; }
- kind= feati->kind;
+ for (feat=0, feati=movei->movfeats;
+ feat<movei->n_movfeats;
+ feat++, feati++) {
+ if ((bestcomb - actual) / feati->weight % feati->posns)
+ continue;
+ if (kind) {
+ if (feati->kind != kind) { ec= EC_MovFeatKindsCombination; goto x; }
+ kind= feati->kind;
+ }
+ motions[n_motions].i= feati;
+ motions[n_motions].posn= bestcomb / feati->weight % feati->posns;
+ n_motions++;
}
- motions[n_motions].i= feati;
- motions[n_motions].posn= bestcomb / feati->weight % feati->posns;
- n_motions++;
- }
- const KindInfo *ki= methodinfos[kind];
+ const KindInfo *ki= &methodinfos[kind];
- if (chg) {
- assert(move == chg->move);
- } else {
- chg= mp_allocate(ki,move,n_motions);
- }
- chg->actual= actual;
- chg->on_done= on_done;
- chg->u= u;
+ if (chg) {
+ assert(move == chg->move);
+ } else {
+ chg= mp_allocate(ki,move,n_motions);
+ }
+ chg->actual= actual;
- ec= ki->request(chg, move, n_motions, motions, maxdelay_ms);
- if (ec) goto x;
+ ec= ki->confirm(chg, move, n_motions, motions, maxdelay_ms);
+ if (ec) goto x;
+ }
return 0;
x:
}
ErrorCode
-movpos_reservechange(Segment *move, int maxdelay_ms, MovPosChange *res_r) {
+movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r) {
MovFeatKind kind= mfk_none;
+ const MovFeatInfo *feati;
+ ErrorCode ec;
+ int feat;
- for (feat=0; feati=movei->movfeats;
- feat<movei->n_movfeats;
+ for (feat=0, feati=move->i->movfeats;
+ feat<move->i->n_movfeats;
feat++, feati++)
if (kind) {
if (feati->kind != kind) return EC_MovFeatKindsCombination;
kind= feati->kind;
}
- const KindInfo *ki= methodinfos[kind];
- ChangeHeader *chg= mp_allocate(ki, move, movei->n_movfeats);
+ const KindInfo *ki= &methodinfos[kind];
+ Change *chg= mp_allocate(ki, move, move->i->n_movfeats);
ec= ki->reserve(chg, move, maxdelay_ms);
if (ec) goto x;
void movpos_unreserve(MovPosChange *res) {
if (!res) return;
- req->ki->destroy(req);
+ res->ki->destroy(res);
}