/** * Record resignation. * <p> * <I>Note: this method should only be called by an AltingBarrier synchronised * on this AltingBarrierBase.</I> * <p> */ internal void resign() { enrolled--; countdown--; if (countdown == 0) { countdown = enrolled; if (enrolled > 0) { AltingBarrierCoordinate.startEnable(); AltingBarrierCoordinate.startDisable(enrolled); AltingBarrier fe = frontEnds; while (fe != null) { fe.schedule(); fe = fe.next; } } } }
/** * This removes the given <i>front-end</i> chained to this <i>alting</i> barrier. * It also nulls its reference to this base - to prevent any attempted reuse! * <p> * <i>Note: this method should only be called by an AltingBarrier synchronised * on this AltingBarrierBase.</I> * <p> * * @param ab the <i>front-end</i> being discarded from this barrier. * This array must be unaltered from one previously delivered by * an {@link #expand expand}. */ internal void contract(AltingBarrier ab) { // assume: (ab != null) AltingBarrier fa = null; AltingBarrier fb = frontEnds; while ((fb != null) && (fb != ab)) { fa = fb; fb = fb.next; } if (fb == null) { throw new AltingBarrierError( "\n*** Could not find front-end in AltingBarrier contract." ); } // deduce: (fb == ab) && (fb != null) // deduce: (fa == null) || (fa.next == fb) // deduce: (fa == null) <==> (frontEnds == ab) // deduce: (fa != null) <==> (fa.next == ab) if (fa == null) { frontEnds = fb.next; } else { fa.next = fb.next; } ab.baseClass = null; if (ab.enrolled) { enrolled--; countdown--; } if (countdown == 0) { countdown = enrolled; if (enrolled > 0) { AltingBarrierCoordinate.startEnable(); AltingBarrierCoordinate.startDisable(enrolled); AltingBarrier fe = frontEnds; while (fe != null) { fe.schedule(); fe = fe.next; } } } else if (countdown < 0) { throw new JCSP_InternalError( "Please report the circumstances to [email protected] - thanks!" ); } }
/** * This removes the given <i>front-ends</i> chained to this <i>alting</i> barrier. * It also nulls all of them - to prevent any attempted reuse! * <p> * <i>Note: this method should only be called by an AltingBarrier synchronised * on this AltingBarrierBase.</I> * <p> * * @param ab the <i>front-ends</i> being discarded from this barrier. * This array must be unaltered from one previously delivered by * an {@link #expand expand}. */ internal void contract(AltingBarrier[] ab) { // assume: (ab != null) && (ab.Length > 0) AltingBarrier first = ab[0]; // counts the number of front-ends whose (hopefully terminated) processes // were still enrolled. int discard = 0; AltingBarrier fa = null; AltingBarrier fb = frontEnds; while ((fb != null) && (fb != first)) { fa = fb; fb = fb.next; } if (fb == null) { throw new AltingBarrierError( "\n*** Could not find first front-end in AltingBarrier contract." ); } // Below, we will null elements of "ab" as we pass though the array. // However, the formal "deduce" and "invariant" comments that follow // relate to code that does not do this. This is safe since the logic // of the code does not depend on values of "ab", subsequent to their // anullment. ab[0].baseClass = null; ab[0] = null; // deduce: (fb == ab[0]) && (fb != null) // deduce: (fa == null) || (fa.next == fb) // deduce: (fa == null) <==> (frontEnds == ab[0]) // deduce: (fa != null) <==> (fa.next == ab[0]) for (int i = 1; i < ab.Length; i++) { // invariant: (fb == ab[i-1]) && (fb != null) if (fb.enrolled) { discard++; } fb = fb.next; if (fb == null) { throw new AltingBarrierError( "\n*** Could not find second (or later) front-end in AltingBarrier contract." ); } if (fb != ab[i]) { throw new AltingBarrierError( "\n*** Removal array in AltingBarrier contract not one delivered by expand." ); } // deduce: (fb == ab[i]) && (fb != null) ab[i].baseClass = null; ab[i] = null; } // deduce: (fb == ab[(ab.Length) - 1]) && (fb != null) if (fb.enrolled) { discard++; } // deduce: (fa == null) <==> (frontEnds == ab[0]) [NO CHANGE] // deduce: (fa != null) <==> (fa.next == ab[0]) [NO CHANGE] if (fa == null) { frontEnds = fb.next; } else { fa.next = fb.next; } enrolled -= discard; countdown -= discard; if (countdown == 0) { countdown = enrolled; if (enrolled > 0) { AltingBarrierCoordinate.startEnable(); AltingBarrierCoordinate.startDisable(enrolled); AltingBarrier fe = frontEnds; while (fe != null) { fe.schedule(); fe = fe.next; } } } else if (countdown < 0) { throw new JCSP_InternalError( "Please report the circumstances to [email protected] - thanks!" ); } }