From: ian Date: Fri, 4 Apr 2008 20:09:17 +0000 (+0000) Subject: new queues, just a few things to do now X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=36b034e28846396658aa0e6f951a48c3eba372b9;p=trains.git new queues, just a few things to do now --- diff --git a/hostside/movpos.c b/hostside/movpos.c index b1c505f..04cb96e 100644 --- a/hostside/movpos.c +++ b/hostside/movpos.c @@ -48,19 +48,26 @@ typedef struct MovPosChangeDetails { * 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 @@ -68,124 +75,130 @@ typedef struct PointMotion { /* Allocated Reserved Enqueued Deleting */ #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; imotions[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 ----------*/ @@ -257,7 +270,7 @@ movpos_requestchange(Segment *back, Segment *move, *Segment *fwd, (*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);