* changing line that
*/
-typedef unsigned Slot;
-
-typedef struct PointReq { /* Allocated Reserved Enqueued Deleting */
- ChangeHeader h;
- int n_motions; /* alloc_.. alloc_.. n_motions 0 */
- PointMotion motions[]; /* undef defined defined defined */
-}
-
-typedef struct PointMotion { /* Allocated Reserved Enqueued Deleting */
- Motion m; /* .i: undef 0 non-0 PT_DEL */
- /* .posn: undef undef defined any */
- Slot deadline; /* undef relative absolute any */
-} PointReq; /* in plan? no yes yes removing */
+typedef unsigned PtSlot;
+typedef int PtSlotSigned;
+
+typedef struct { /* Allocated Reserved Confirmed */
+ /* in queue? absent reserved confirmed */
+ ChangeHeader h; these two */
+ Slot deadline; /* ~0 relative absolute <- `statedet' */
+ int n_motions; /* alloc'd alloc'd undone fields */
+ Motion motions[];/* [0].i: 0 0 non-0 <- indicate */
+ /* [..].i: undef undef non-0 state */
+ /* .posn: undef undef defined */
+} PointReq;
+ /* We abbreviate these states as A R C
+ * There are also intermediate states where the req's
+ * statedet fields do not agree with the queue it's on.
+ * We write these as, for example,
+ * AR to mean statedet says Allocated, but queued on pt_reserved
+ * A? to mean statedet says Allocated, but may be queued
+ * etc. They are only allowed while we are in a pt_... method function.
+ */
/* We increment cslot when we issue a POINT command to the PIC.
* deadline represents the latest allowable value of cslot
#define CDU_RECHARGE 250 /*ms*/
#define POINT_MOVEMENT 50 /*ms*/
-#define PT_MAX_PLAN 15
-static Slot pt_cslot;
-static int pt_planlen;
-static PointMotion *pt_plan[PT_MAX_PLAN];
+#define PT_MAX_QUEUE 15
-#define PT_DEL ((const MovFeatInfo*)info_segments) /* some random struct */
+static PtSlot pt_cslot;
-static SomeChange pt_allocate(int alloc_motions) {
- PointReq= *p;
+/*
+ * We maintain two queues, one for reserved one for actually confirmed
+ * requests where we know what we're doing.
+ */
- p= mmalloc(sizeof(*p) + alloc_motions * sizeof(p->motions[0]));
- p->n_motions= alloc_motions;
- return (SomeChange*)p;
-}
+todo
+ actually fire points: use item, and remove it, etc.
+ write check routine
-static pt_maxdelay_reldeadline(int maxdelay_ms) {
+typedef struct {
+ int n;
+ PointReq *l[PT_MAX_QUEUE];
+} PointQueue;
+
+static PointQueue pt_confirmed, pt_reserved;
+
+#define PT_DEL ((const MovFeatInfo*)info_segments) /* some random struct */
+
+static pt__maxdelay_reldeadline(int maxdelay_ms) {
return (maxdelay_ms - POINT_MOVEMENT + CDU_RECHARGE) / CDU_RECHARGE;
}
-static ErrorCode pt_insertreq(PointReq *pt) {
- int i;
-
- int n_add= pt->n_motions;
- if (n_add==0) return 0;
-
- int new_planlen= pt_planlen + new->n_motions;
- if (new_planlen > PT_MAX_PLAN) return EC_BufferFull;
-
- insat= pt_planlen;
- new_reldeadline= pt_motion_reldeadline(pt->motions[0].deadline);
- for (;;) {
- if (insat<=0) break;
- delaying_reldeadline= pt_motion_reldeadline(pt_plan[insat]->deadline);
- if (new_reldeadline >= delaying_reldeadline) break;
- int copyto= insat + n_add;
- if (copyto > new_reldeadline) return EC_Points;
- insat--;
- }
- if (insat + n_add - 1 > new_reldeadline)
- return EC_Points;
-
- int copyto= insat + n_add;
- memmove(&pt_plan[copyto], &pt_plan[insat], sizeof(pt_plan[0]) * n_add);
- for (i=0; i<n_add; i++)
- pt_plan[insat+i]= &pt->motions[i];
+static void pt__queue_remove_index(PointQueue *q, int index) {
+ q->n--;
+ memmove(&q->l[index], &q->l[index+1], sizeof(q->l[0]) * (q->n - index));
+}
- while (insat>0 &&
-
- < (moving_reldeadline=
-
+static void pt__req_compar(const void *av, const void *bv) {
+ PointQueue *const *a= av;
+ PointQueue *const *b= av;
+ return (PtSlotSigned)((*b)->deadline - (*a)->deadline);
+}
- insat[-1]
- int this_rel
+static void pt__queue_remove_item(PointQueue *q, PointReq *r) {
+ PointQueue **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_reserve(SomeChange *chg, Segment *move, int maxdelay_ms) {
- PointReq *p= (PointReq*)chg;
- PointMotion *m;
- int mi;
- Slot deadline= pt_reldeadline(maxdelay_ms);
-
- for (mi=0, m=p->motions; mi < p->n_motions; mi++, m++) {
- m->m.i= 0;
- m->deadline= deadline;
+static void pt__dequeue(PointReq *r) { /* X->XA */
+ if (r->motions[0].i) {
+ pt__queue_remove_item(&pt_confirmed, r);
+ } else if (~r->deadline) {
+ pt__queue_remove_item(&pt_reserved, r);
}
- return pt_insertreq(p);
}
-static int point__putbefore(PointReq *new, PointReq *existing) {
- return new->startby < existing->startby;
+static void pt_destroy(SomeChange *chg) { /* X->XA and then free it */
+ PointReq *r= (PointReq*)chg;
+ pt__dequeue(r);
+ free(r);
}
-static ErrorCode point__enqueue(PointReq *p, int count, int maxdelay_ms,
- Slot minrelslot) {
- Slot relslot;
- PointReq *ref;
-
- relslot= (maxdelay_ms - POINT_MOVEMENT + CDU_RECHARGE) / CDU_RECHARGE
- - count;
- if (relslot < minrelslot) return EC_Point;
+static void pt__mark_as_allocated(PointReq *r) { /* AX->X */
+ /* Sets statedet fields for Allocated */
+ r->deadline= ~(PtSlot)0;
+ r->motions[0].i=0;
+}
- p->startby= cslot + relslot;
+static ErrorCode pt__enqueue(PointQueue *q, PointReq *r) { /* XA -> X */
+ ErrorCode ec; /* ... where X is R or C and corresponds to q */
+ /* or on error, XA -> A */
- if (!queue.tail || !point__putbefore(p, queue.tail)) {
- DLIST2_APPEND(queue,p,qe);
- return;
+ if (q->n == PT_MAX_QUEUE) {
+ return EC_BufferFull;
}
- if (point_putbefore(p, lastinsert)) {
- for (ref=lastinsert;
- ref->qe.back && point_putbefore(p, ref);
- ref= ref->qe.back);
- DLIST2_INSERT_BEFORE(queue,p,qe,ref);
- } else {
- for (ref=lastinsert;
- ref->qe.next && !point_putbefore(p, ref);
- );
- DLIST2_INSERT_AFTER(queue,p,qe,ref);
-
-
-
- if (!lastinsert)
-}
-static ErrorCode point_reserve(SomeChange *chg, Segment *move,
- int maxdelay_ms) {
-
+ for (insat= q->n;
+ insat>0 && CLOCK_COMPARE(r->deadline, <, q->l[insat-1]->deadline);
+ insat--)
+ q->l[insat]= q->l[insat-1];
+ q->l[insat]= r;
+ q->n++;
- cslot + maxdelay_ms / POINT_EVERY_MS this is not right;
-
+ return pt_check();
+ /* if this fails, indep machinery calls pt_destroy which dequeues */
+}
- ErrorCode (*request)(SomeChange*, Segment *move,
- int n_motions, const Motion*, int maxdelay_ms);
- void (*destroy)(SomeChange*);
+static SomeChange pt_allocate(int alloc_motions) {
+ PointReq= *r;
+ r= mmalloc(sizeof(*r) + alloc_motions * sizeof(r->motions[0]));
+ r->deadline= ~(PtSlot)0;
+ r->n_motions= alloc_motions;
+ r->motions[0].i= 0;
+ return (SomeChange*)r;
+}
-convert incoming latest's into queue lengths as simple counts
-maintain latest count number for each
+static ErrorCode pt_reserve(SomeChange *chg, Segment *move, int maxdelay_ms) {
+ PointReq *r= (PointReq*)chg;
+ r->deadline= pt_reldeadline(maxdelay_ms);
+ return pt_queue_add(&pt_reserved, r);
+}
+static ErrorCode pt_request(SomeChange *chg, Segment *move,
+ int n_motions, const Motion *motions,
+ int maxdelay_ms) {
+ /* [AR]->C; on error: [AR]->X */
+ PointReq *r= (PointReq*)chg;
+ PtSlot newdeadline;
+ int allow_failure;
+
+ assert(n_motions <= r->n_motions);
+ newdeadline= pt_reldeadline(maxdelay_ms) + cslot;
+ allow_failure= newdeadline < r->deadline;
+
+ /* state [AR] */
+ pt__dequeue(r);
+ /* state [AR]A */
+ assert(n_motions>0 && motions[0].i);
+ memcpy(r->motions, motions, sizeof(r->motions[0])*n_motions);
+ r->n_motions= n_motions;
+ r->deadline= newdeadline + pt_cslot;
+ /* state CA */
+ ec= pt__enqueue(&pt_confirmed, r);
+ assert(allow_failure || !ec);
+ return ec;
+}
/*---------- method-independent machinery ----------*/
(*req_io)->on_done= on_done;
(*req_io)->u= u;
} else {
- if (n_motions > (*req_io)->move->i->n_movfeats) { ec= EC_Invalid; return; }
+ if (move != (*req_io)->move) { ec= EC_Invalid; return; }
}
ec= mi->request((SomeChange*)*req_io, move, n_motions, motions, maxdelay_ms);