package junior.core; import junior.*; /** Preemption instruction. */ public class Until extends FlushableInstruction implements Awakable, Flushable { int waitingType () {return SAT;} Instruction body = null; Instruction handler = null; byte bodyStatus = FRESH; byte handlerStatus = FRESH; boolean activeBody = false; boolean activeHandle = false; public Until(Configuration config, Program b, Program h){ this.config = (Config) config; body = (Instruction) b ; handler = (Instruction) h; } public void reset(){ super.reset(); body.reset (); handler.reset (); bodyStatus = FRESH; handlerStatus = FRESH; activeBody = activeHandle = false; } public String toString(){ if (handler instanceof Nothing) return "do "+body+" until "+config; return "do "+body+" until "+config+" actual "+handler+" end"; } void activ () { postedForFlush = false; if (activeHandle) { handlerStatus = status = handler.activate (context, envt, this); } else { activeBody = true; bodyStatus = body.activate (context, envt, this); if (bodyStatus == TERM) { activeBody = false; status = bodyStatus; makeSureConfigIsUnposted (); makeSureIWillNotFlush (); } else { makeSureConfigIsFixedOrPosted (); if (isSatisfied && (bodyStatus == STOP)) applyPreemption (); else { // configuration not satisfied or suspended body makeSureIWillFlush (); status = SUSP; } } } } void applyPreemption () { /* if (activeHandle) trace (ERR_LEVEL, "Until: applyPreemption with handler already active !!!"); else { /* if (bodyStatus != STOP) { if (!context.isFlushingInstant ()) trace (ERR_LEVEL, "Until: applyPreemption when !endOfInstant and body not Stopped !!!"); } */ body.cancel (); activeBody = false; activeHandle = true; makeSureIWillNotFlush (); if (context.isFlushingInstant ()) { status = STOP; beReactivable (); } else { handlerStatus = status = handler.activate (context, envt, this); } /* } */ } public boolean awake (int val) { boolean finished = false; isSatisfied = true; if (bodyStatus == STOP) { applyPreemption (); context.addRecall (this); } else if ((bodyStatus == SUSP) || (bodyStatus == FRESH)) makeSureIWillFlush (); waitingPosted = false; return true; // once awakened, I don't care anymore... } public void flushInstant () { postedForFlush = false; if (isSatisfied && (bodyStatus != TERM)) { applyPreemption (); // je suis en "endOfInstant", pas de pb...! } else { bodyStatus = FRESH; // pour si bodyStatus est ý stop } } public void hasChanged (Instruction callee, byte s) { if (callee == body) { bodyStatus = s; if (bodyStatus == STOP) { if (isSatisfied) applyPreemption (); else { makeSureIWillFlush (); // pour remettre bodyStatus ý FRESH ! } } else if (bodyStatus == TERM) { status = TERM; makeSureConfigIsUnposted (); makeSureIWillNotFlush (); } } else if (callee == handler) { status = handlerStatus = s; } tellCaller (); } void cancel () { if (status != TERM) { makeSureIWillNotFlush (); makeSureConfigIsUnposted (); if (activeHandle) { if (handlerStatus == FRESH) context.cancelReactivable (this); else if (handlerStatus != TERM) handler.cancel (); } else if (activeBody) body.cancel (); } } public Program copy () {return new Until (config.copy (), body.copy (), handler.copy ());} public Program residual () { if (status == TERM) return null; if (activeHandle) { // le body ne m'intÈresse plus (je ne suis plus un 'Until') if (handlerStatus == FRESH) return handler.copy (); else return handler.residual (); } else { Program brest = body.residual (); return new Until (config.copy (), brest, handler.copy ()); } } public void linkObject (Object o) { linked = o; // useful ? if (body != null) body.linkObject (o); if (handler != null) handler.linkObject (o); } }