package abstrasy.pcfx;
import abstrasy.Heap;
import abstrasy.Interpreter;
import abstrasy.Node;
import abstrasy.PCoder;
import abstrasy.interpreter.BaseContextSnapshot;
/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
* http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/
public class PCFx_ensure extends PCFx {
public PCFx_ensure() {
}
/**
* eval
*
* @param startAt Node
* @return Node
* @throws Exception
* @todo Implémenter cette méthode abstrasy.PCFx
*/
public Node eval(Node startAt) throws Exception {
/*
* forme (insure{...} termination{...})
*
* Exécute la section insure puis, dans tous les cas, la section termination dans
* contexte void et fail-over (donc sans aucun retour qu'il s'agisse d'un résultat
* ou d'une exception).
*
* Ainsi, même en cas de problème, la section termination est toujours exécutée
* même si le programme est en cours d'arrêt.
*
* Si une exception se produit à l'intérieur de la section insure et qu'elle n'est
* pas récupérée par une structure try, l'exception est automatiquement propagée
* après l'exécution de la partie termination.
*
* Dans tous les cas, la section termination est exécutée qu'il y ai ou non un
* évènement (exception par exemple). De plus, la section termination ne peut
* reporter de nouvelle exception ou produire de valeur de retour.
*
* (insure{...} termination{...}) permet de mettre en place des procédures de terminaison
* invariantes. Ainsi, si un acteur est supprimé, on est sûr que la section termination
* sera exécutée dans tous les cas.
*
* Il ne doit pas s'agire nécessairement de procédures de finalité normale (ou on
* ferme des fichiers par exemple), mais plutôt une section où l'on s'assure que
* les éléments reçoivent le traitement final adhéquat (donc vérifier si les fichiers
* sont bien fermés et, si ce n'est pas le cas, les fermer).
*
*/
startAt.isGoodArgsCnt(4);
Node xnode = startAt.getSubNode(1, Node.TYPE_LAZY);
startAt.requirePCode(2, PCoder.PC_TERMINATION);
Node enode = startAt.getSubNode(3, Node.TYPE_LAZY);
Node res = null;
/*
* obtenir les paramètres avant le début de l'exécution de la section insure{...} ...
*/
Interpreter interpreter = Interpreter.mySelf();
BaseContextSnapshot contextSnapshot=new BaseContextSnapshot(interpreter);
Exception allExcep = null;
/*
* exécuter la section hook et capturer une éventuelle exception...
*/
try {
Heap.push();
res = xnode.exec(true);
Heap.pull();
}
catch (Exception ex) {
allExcep = ex;
}
/*
* On doit rétablir un environnement exécutable suffisament stable même en cas de
* suppression ou d'exception grave...
*
* La premère chose à faire consiste à bloquer temporairement l'action, si on est
* dans une section temporisée...
*/
long old_deadlockTime_after = interpreter.getDeadlockTime();
boolean old_timeOutCheck_after = interpreter.isTimeOutCheck();
boolean old_timeOutTimerStatus_after = interpreter.getTimeOutTimer().isRunning();
if (old_timeOutCheck_after || old_timeOutTimerStatus_after) {
interpreter.setTimeOutCheck(false);
interpreter.getTimeOutTimer().stop();
}
boolean canloop_after = interpreter.isCanLoop();
boolean inloop_after = interpreter.isInLoop();
long callerSignature_after = interpreter.getCallerSignature();
boolean tailNode_after = interpreter.isTailNode();
boolean terminalNode_after = interpreter.isTerminalNode();
Node oldThisNode_after = interpreter.getThisFunction();
Node oldWrapperNode_after = interpreter.getWrapperFunction();
Node oldSelfNode_after = interpreter.getSelf();
Node oldRootNode_after = interpreter.getRoot();
Node oldIfaceNode_after = interpreter.getIface();
boolean stop_status_after = interpreter.isThreadStopped();
boolean breakingFromSemaphore_after = interpreter.isBreakingFromSEMAPHORE();
boolean endingFromSemaphore_after = interpreter.isEndingFromSEMAPHORE();
int old_equStackLock_A = interpreter.getEquStack_A().lock();
int old_equStackLock_B = interpreter.getEquStack_B().lock();
int old_compareStackLock_A = interpreter.getCompareStack_A().lock();
int old_compareStackLock_B = interpreter.getCompareStack_B().lock();
/*
* Restaurer les paramètres qui ont précédé l'exécution de la section insure...
*
* En cas de problème grave on rétabli les fonctionnlité de base...
*/
contextSnapshot.restore();
/*
* Si l'acteur est en état de suppression...
*
* Passe en mode Fail-over...
*/
boolean old_failOver=interpreter.isFailOver();
interpreter.setFailOver(true);
/*
* exécuter termination{...}...
*/
Node tres=null;
try{
Heap.push();
tres=enode.exec(true);
Heap.pull();
}
catch(Exception e){
Interpreter.Log("Exception in termination:\n"+e);
}
if(tres!=null){
Interpreter.Log("Result value of termination:\n"+tres.toString());
}
/*
* De nouveau, si la pile n'est pas correctement rétablie...
*/
contextSnapshot.restoreGlobalOnly();
/*
* restaurer les paramètres qui ont précédé l'exécution de la section A...
*
* Ceux-ci peuvent être traités par un (try{...} catch{...})
*/
interpreter.setCanLoop(canloop_after);
interpreter.setInLoop(inloop_after);
interpreter.setCallerSignature(callerSignature_after);
interpreter.setTailNode(tailNode_after);
interpreter.setTerminalNode(terminalNode_after);
interpreter.setThisFunction(oldThisNode_after);
interpreter.setWrapperFunction(oldWrapperNode_after);
interpreter.setSelf(oldSelfNode_after);
interpreter.setRoot(oldRootNode_after);
interpreter.setIface(oldIfaceNode_after);
interpreter.getEquStack_A().unlock(old_equStackLock_A);
interpreter.getEquStack_B().unlock(old_equStackLock_B);
interpreter.getCompareStack_A().unlock(old_compareStackLock_A);
interpreter.getCompareStack_B().unlock(old_compareStackLock_B);
/*
* Restaurer le système de timer...
*/
interpreter.setDeadlockTime(old_deadlockTime_after);
interpreter.setTimeOutCheck(old_timeOutCheck_after);
if (old_timeOutCheck_after || old_timeOutTimerStatus_after) {
interpreter.setTimeOutCheck(true);
interpreter.getTimeOutTimer().start();
}
/*
* Rétablir les états de suppression de l'acteur...
*
* Cette partie doit notamment tenir compte de (exit).
*
* Combinaison des états avant/après inclusive...
*
*/
interpreter.setThreadStopped(stop_status_after || interpreter.isThreadStopped());
interpreter.setBreakingFromSEMAPHORE(breakingFromSemaphore_after || interpreter.isBreakingFromSEMAPHORE());
interpreter.setEndingFromSEMAPHORE(endingFromSemaphore_after || interpreter.isEndingFromSEMAPHORE());
interpreter.setTimeOutRaising(old_timeOutCheck_after);
/*
* enlever le fail-over...
*/
interpreter.setFailOver(old_failOver);
/*
* Reporter l'exception initiale...
*/
if(allExcep!=null){
/*
* déclencher l'exception capturée...
*/
throw allExcep;
}
else{
interpreter.throwInterThreadException();
}
/*
* Si tout s'est bien passé, on continue sans souci...
*/
return res;
}
}