package buffalo.dataStructures; /** Classe décrivant une <CODE>Opération</CODE> élémentaire d'une <CODE>Tâche</CODE> sur un <CODE>Buffer</CODE>. <BR> <BR> On peut considérer qu'une <CODE>Opération</CODE> est muni de tous les attributs suivants : <UL> <LI> Une <CODE>Tâche</CODE>T</CODE> qui l'exécute, cette <CODE>Tâche</CODE> sera ici appellée <CODE>activeTask</CODE>. </LI> <LI> Un <CODE>Buffer</CODE> <CODE>B</CODE> vers lequel s'effectue cette <CODE>Opération</CODE>. </LI> <LI> Une <CODE>Tâche</CODE> <CODE>T'</CODE>qui partage le <CODE>Buffer</CODE> avec <CODE>T</CODE>, appelée dans les méthodes <CODE>PassiveTask</CODE>. </LI> <LI> Un <CODE>rang n</CODE>dans l'ordre d'exécution, marquant une contrainte de précédence vis-à-vis des contraintes de <CODE>rang</CODE> supérieur. Le successeur immédiat, donc de <CODE>rang (n+1)</CODE>, est appelé ici <CODE>nextFixedOperation</CODE>; on devine que le prédécesseur immédiat, de <CODE>rang (n-1)</CODE>, est appelé <CODE>previousFixedOperation</CODE>. </LI> <LI> Un chaînage vers une <CODE>Opération</CODE> notée <CODE>o'</CODE>, et telle que si nous notons l'<CODE>Opération</CODE> courante <CODE>o</CODE>, des contraintes liées aux dimensions des <CODE>Buffers</CODE> ou à l'ordre des <CODE>Opérations</CODE> ont pour conséquence le fait que <CODE>o</CODE> devra s'exécuter avant <CODE>o'</CODE>. <CODE>o'</CODE> est ici désigné comme étant la <CODE>nextBufferedOperation</CODE> de <CODE>o</CODE>, tout comme <CODE>o</CODE> est la <CODE>previousBufferedOperation</CODE> de <CODE>o'</CODE>. </LI> <LI> Comme de même il existe deux types de contraintes : de <CODE>fullBuffer</CODE> et de <CODE>emptyBuffer</CODE>, un attribut permet de savoir si la contrainte de précedence mentionnée ci-dessus est pour cette <CODE>Opération</CODE> une contrainte de <CODE>fullBuffer</CODE> ou non. </LI> </UL> <BR> */ public class Operation { /* Buffer sur lequel s'effectue l'opération */ private Buffer buffer; /* Tâche effectuant cette opération */ private Task activeTask; /* Tâche liée à activeTask par un le Buffer de l'opération courante */ private Task passiveTask; /* Index de l'operation courante */ private int indexOfMe; /* Index de l'opération B liée à celle de l'instance courante A par une relation de famine ou d'interblocage telle que B doit s'exécuter après A */ private Operation nextBufferedOperation; /* Réciproque de la méthode précédente */ private Operation previousBufferedOperation; /* Image par N de this. */ private int myImageByN; /*--------------------------------------------------------------------------------------*/ /* Inutile en dehors du package... */ Operation(int indexOfBuffer, int indexOfTask, int indexOfMe) { this.buffer = Buffer.get(indexOfBuffer); this.activeTask = Task.get(indexOfTask); this.passiveTask = Buffer.get(indexOfBuffer).getOtherTask(this.activeTask.getIndex()); //Si l'opération n'est pas conforme aux buffers connectés. if(passiveTask==null) { System.out.println("***********\n" + "WARNING : \n" + "Buffer " + indexOfBuffer + " is not connected to task " + indexOfTask + "\n***********\n" ); } this.indexOfMe = indexOfMe; myImageByN = this.buffer.getNbInversedN(this.activeTask); this.buffer.addOperationToN(this, this.activeTask); } /*--------------------------------------------------------------------------------------*/ /** Retourne le <CODE>rang</CODE> de l'<CODE>Opération</CODE> en cours. */ public int getIndex() { return indexOfMe; } /*--------------------------------------------------------------------------------------*/ /** Retourne la <CODE>Tâche</CODE> <CODE>T</CODE> effectuant l'<CODE>Opération</CODE> courante. */ public Task getActiveTask() { return activeTask; } /*--------------------------------------------------------------------------------------*/ /** Retourne la <CODE>Tâche</CODE> <CODE>T'</CODE> partageant ce <CODE>Buffer</CODE> avec <CODE>T</CODE>. */ public Task getPassiveTask() { return passiveTask; } /*--------------------------------------------------------------------------------------*/ /** Retourne l'<CODE>Opération</CODE> suivant celle de l'instance courante sur la même <CODE>Tâche</CODE>, <CODE>null</CODE> si elle n'existe pas. */ public Operation getNextFixedOperation() { if(this.getIndex()+1==activeTask.getNbOperations()) { return null; } else { return activeTask.getOperation(this.getIndex() + 1); } } /*--------------------------------------------------------------------------------------*/ /** Retourne l'<CODE>Opération</CODE> précédent celle de l'instance courante sur la même <CODE>Tâche</CODE>, <CODE>null</CODE> si elle n'existe pas. */ public Operation getPreviousFixedOperation() { if (this.getIndex()==0) { return null; } else { return activeTask.getOperation(this.getIndex() - 1); } } /*--------------------------------------------------------------------------------------*/ /** Soit une <CODE>Opération</CODE> <CODE>B</CODE> liée à celle de l'instance courante <CODE>A</CODE> par une relation de <CODE>Buffer</CODE> plein ou de <CODE>Buffer</CODE> vide telle que <CODE>B</CODE> doit s'exécuter <U>après</U> <CODE>A</CODE>; cette méthode retourne <CODE>B</CODE> si une telle <CODE>Opération</CODE> existe, <CODE>null</CODE> sinon. */ public Operation getNextBufferedOperation() { return nextBufferedOperation; } /*--------------------------------------------------------------------------------------*/ /** Soit une <CODE>Opération</CODE> <CODE>B</CODE> liée à celle de l'instance courante <CODE>A</CODE> par une relation de <CODE>Buffer</CODE> plein ou de <CODE>Buffer</CODE> vide telle que <CODE>B</CODE> doit s'exécuter <U>avant</U> <CODE>A</CODE>; cette méthode retourne <CODE>B</CODE> si une telle <CODE>Opération</CODE> existe, <CODE>null</CODE> sinon. */ public Operation getPreviousBufferedOperation() { return previousBufferedOperation; } /*--------------------------------------------------------------------------------------*/ /** Soit une <CODE>Opération</CODE> <CODE>B</CODE> liée à celle de l'instance courante <CODE>A</CODE> par une relation de <CODE>Buffer</CODE> plein ou de <CODE>Buffer</CODE> vide telle que <CODE>B</CODE> doit s'exécuter <U>avant</U> <CODE>A</CODE>; cette méthode permet de déterminer cette contrainte en passant à l'<CODE>Opération</CODE> courante son successeur <CODE>nextBufferedOperation</CODE>.<BR>Cette méthode se charge de doubler le chaînage (ou de vérifier si il est effectivement double). */ public void setNextBufferedOperation(Operation nextBufferedOperation) { if ((nextBufferedOperation == null)&&(this.nextBufferedOperation != null)) { Operation formerNextBufferedOperation = this.nextBufferedOperation; this.nextBufferedOperation = null; formerNextBufferedOperation.setPreviousBufferedOperation(null); } else { if (this.nextBufferedOperation != nextBufferedOperation) { this.setNextBufferedOperation(null); this.nextBufferedOperation = nextBufferedOperation; nextBufferedOperation.setPreviousBufferedOperation(this); } } } /*--------------------------------------------------------------------------------------*/ /** Soit une <CODE>Opération</CODE> <CODE>B</CODE> liée à celle de l'instance courante <CODE>A</CODE> par une relation de <CODE>Buffer</CODE> plein ou de <CODE>Buffer</CODE> vide telle que <CODE>B</CODE> doit s'exécuter <U>après</U> <CODE>A</CODE>; cette méthode permet de déterminer cette contrainte en passant à l'<CODE>Opération</CODE> courante son prédécesseur <CODE>previousBufferedOperation</CODE>.<BR> Cette méthode se charge de doubler le chaînage (ou de vérifier si il est effectivement double). */ public void setPreviousBufferedOperation(Operation previousBufferedOperation) { if ((previousBufferedOperation == null)&&(this.previousBufferedOperation != null)) { Operation formerPreviousBufferedOperation = this.previousBufferedOperation; this.previousBufferedOperation = null; formerPreviousBufferedOperation.setNextBufferedOperation(null); } else { if (this.previousBufferedOperation != previousBufferedOperation) { this.setPreviousBufferedOperation(null); this.previousBufferedOperation = previousBufferedOperation; previousBufferedOperation.setNextBufferedOperation(this); } } } /*--------------------------------------------------------------------------------------*/ /* Soit <CODE>I</CODE> l'indice de l'<CODE>Opération</CODE> <CODE>B</CODE> liée à celle de l'instance courante <CODE>A</CODE> par une relation de famine ou d'interblocage telle que <CODE>B</CODE> doit s'exécuter <U>après</U> <CODE>A</CODE>. Cette méthode retourne <CODE>True</CODE> si cette contrainte est une contrainte de <CODE>DeadLock</CODE>, <CODE>False</CODE> dans le cas contraire. <U>Attention</U> : Si <CODE>nextOperation</CODE> est <CODE>null</CODE>, cette fonction jettera une <U>Exception</U>! public boolean isFullBufferConstraint() { return isFullBufferConstraint; } */ /*--------------------------------------------------------------------------------------*/ /** Retourne le <CODE>Buffer</CODE> sur lequel cette <CODE>Opération</CODE> s'effectue. */ public Buffer getBuffer() { return buffer; } /*--------------------------------------------------------------------------------------*/ /** Retourne l'image par <CODE>N</CODE> de cette opération. */ public int getN() { return myImageByN; } /*--------------------------------------------------------------------------------------*/ /** Retourne cette <CODE>Opération</CODE> sous format chaîne de caractères. */ public String toString() { return new String(new Integer(buffer.getIndex()).toString()); } }