From: ian Date: Sun, 13 Feb 2005 18:20:29 +0000 (+0000) Subject: wip before redo segment justarrive stuff X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=ca6026654b2f7d44abeb3f2adf5d05dec4bc479c;p=trains.git wip before redo segment justarrive stuff --- diff --git a/hostside/safety.c b/hostside/safety.c index 099bad0..54b7cd8 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -7,18 +7,66 @@ State safety_actual; typedef struct TrackLocation TrackLocation; -struct TrackLocation { +struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */ SegmentNum segn; /* current segment */ long into; /* distance from start of segment */ unsigned backwards:1; /* if 1, into is positive and measured from end */ }; -void trackloc_further(TrackLocation *tloc, long *remain_io); +const SegmentLinkInfo *trackloc_segmentlink_near(const TrackLocation *tloc) { + SegmentState *seg = s->seg[tloc->segn]; + const SegmentInfo *segi= &safety_segis[tloc->segn]; + + return (tloc->backwards ? &segi->forwards : + seg->pt_sideways ? &segi->sideways : + &segi->backwards); +} + +const SegmentLinkInfo *trackloc_segmentlink_far(const TrackLocation *tloc) { + SegmentState *seg = s->seg[tloc->segn]; + const SegmentInfo *segi= &safety_segis[tloc->segn]; + + return (tloc->backwards ? &segi->backwards : + seg->pt_sideways ? &segi->sideways : + &segi->forwards); +} + +long trackloc_remaininseg(const TrackLocation *tloc) { + /* Returns dist that tloc can advance before it goes into next segment. */ + State *s = &safety_state; + SegmentState *seg = s->seg[tloc->segn]; + const SegmentInfo *segi= &safety_segis[tloc->segn]; + const SegmentLinkInfo *lnki_near, *lnki_far; + long segment_len; + + lnki_near= trackloc_segmentlink_near(tloc); + lnki_far= trackloc_segmentlink_far(tloc); + segment_len= linki_near->dist + link_far->dist; + assert(tloc->into <= segment_len); + return segment_len - tloc->info; +} + +void trackloc_further(TrackLocation *tloc, long *remain_io) { /* Advances tloc, decrementing *remain_io, until either * *remain_io becomes zero, or tloc->segn changes. */ - -long trackloc_remaininseg(const TrackLocation *tloc); - /* Amount that tloc can advance before it goes into next segment. */ + State *s = &safety_state; + SegmentState *seg = s->seg[tloc->segn]; + const SegmentInfo *segi= &safety_segis[tloc->segn]; + const SegmentLinkInfo *lnki_far; + + segment_remain= trackloc_remaininseg(tloc); + + if (*remain_io <= segment_remain) { + tloc->into += *remain_io; + *remain_io= 0; + } else { + lnki_far= trackloc_segmentlink_far(tloc); + *remain_io -= segment_remain; + tloc->segn= lnki_far->next; + tloc->into= 0; + tloc->backwards ^= lnki_far->next_backwards; + } +} static voi seg_clear_stale(SegmentState *seg) { if (!seg->tr_updated) { @@ -27,10 +75,44 @@ static voi seg_clear_stale(SegmentState *seg) { } } +void lay_train_checkclash(ErrorCode *ec, SegmentLinkInfo *lnki + TrainNum tran,) { + SegmentNum clash_segn; + SegmentState *clash_seg; + TrainNum clash_tran; + TrainState *clash_tra; + + clash_segn= lnki->clashing; + if (clash_segn == NOTA(Segment)) return; + + clash_seg= &s->segs[lnki->clashing]; + if (!clash_seg->owned) return; + + clash_tran= clash->owner; + clash_tra= &s->tras[clash_tran]; + + if (clash_tra->justarrived) { + TrackLocation clash_loc; + clash_loc.segn= clash_tra->foredetect; + clash_loc. + + += &s->segs[lnki->clashing]; + if (clash-> + + lay_train_checkclash2( + static void lay_train(ErrorCode *ec, TrainNum tran, TrackLocation tloc, long advance, - unsigned detect, unsigned clash_if_updated) { + unsigned pass) { + /* pass 0: update actual train location, check for train clashing + * with itself (ie, fail if we find segment with same train and + * tr_updated set. + * pass 1: update detection only. Clashingness checking is + * done where it is convenient not to avoid it, but is not + * necessary. */ SegmentState *seg; + const SegmentInfo *segi; long overall, remain; if (*ec) return; @@ -38,26 +120,44 @@ static void lay_train(ErrorCode *ec, TrainNum tran, remain= overall= advance + tra->speed * SPEED_CLEAR_MULT; for (;;) { - seg= s->segs[tloc.segn]; - if (clash_if_updated && seg->tr_updated) { - *ec= safety_problem(tloc.segn, tran, tran, "collision with itself"); - return; - } - if (seg->owned) { - if (seg->owner != tran) { - *ec= safety_problem(tloc.segn, tran, seg->owner, "collision"); + seg= &s->segs[tloc.segn]; + segi= &info_segment[tloc.segn]; + + if (pass==0) { + if (seg->tr_updated) { + *ec= safety_problem(tloc.segn, tran, tran, "collision with itself"); return; } - seg_clear_stale(seg); + if (seg->owned) { + if (seg->owner != tran) { + *ec= safety_problem(tloc.segn, tran, seg->owner, "collision"); + return; + } + seg_clear_stale(seg); + } } + seg->owned= 1; seg->owner_backwards= tloc.backwards; seg->tr_updated= 1; seg->tran= tran; + seg->tr_justarrived= pass==0 && remain && tra->justarrived; + + lay_train_checkclash(ec, trackloc_segmentlink_near()); + if (!remain && tra->justarrived) { + + + if (tloc.into <= JUSTARRIVED_INTOMAX) { + seg->tr_justarrived= 1; + } else { + lay_train_checkclash(&ec, trackloc_segmentlink_far()); + } + + dist_until= (overall - remain) - advance; time_until= (SPEED_FACTOR * dist_until) / tra->speed; - *(detect ? &seg->until_detect : &seg->until_here)= time_until; + *(pass==0 ? &seg->until_here : &seg->until_detect)= time_until; if (!remain) break; trackloc_further(&tloc, &remain); @@ -109,17 +209,6 @@ void safety_train_changed(TrainNum tran) { if (ec) return ec; - - - - segi= &safety_segis[segn]; - lnki1= (seg->reverse ? &segi->forwards : - seg->sideways ? &segi->sideways : - &segi->backwards); - lnki2= (seg->reverse ? &segi->backwards : - seg->sideways ? &segi->sideways : - &segi->forwares); - tloc.segn= segn; tloc.into= diff --git a/hostside/safety.h b/hostside/safety.h index 06101d4..aaedd5b 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -21,8 +21,9 @@ typedef struct { typedef struct { unsigned owned:1, /* this track segment is reserved for a train */ - owner_backwards:1, /* train's motion is (would be) backwards wrt track */ + tr_backwards:1, /* train's motion is (would be) backwards wrt track */ pt_sideways:1, /* points are set to `alternative'. (no points?: 0) */ + pt_moving:1, /* points have been told to change, sideways is new state */ autostop:1, /* owning train is slow and wants to stop on detection */ tr_updated:1; /* for use by safety_train_changed etc.; otherwise 0 */ TimeInterval until_here, /* ) nonnegative; */ /* ) always valid but */ @@ -32,7 +33,7 @@ typedef struct { } SegmentState; typedef struct { - unsigned next_rev:1; + unsigned next_backwards:1; SegmentNum next; SegmentNum clashing; Distance dist;