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());
}
}