-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathControlRecicladoCSP.java
More file actions
244 lines (202 loc) · 7.04 KB
/
ControlRecicladoCSP.java
File metadata and controls
244 lines (202 loc) · 7.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
// Esqueleto para realizar la practica mediante paso de mensajes y
// peticiones aplazadas (rellenad el código donde dice COMPLETAD y
// eliminad todos los comentarios espúreos, como este, antes de
// realizar la entrega)
package cc.controlReciclado;
import org.jcsp.lang.*;
// importar estructuras de datos para almacenar peticiones aplazadas
import java.util.LinkedList;
import java.util.Queue;
public class ControlRecicladoCSP implements ControlReciclado, CSProcess {
// constantes varias
private enum Estado {
LISTO, SUSTITUIBLE, SUSTITUYENDO
}
private final int MAX_P_CONTENEDOR; // a definir en el constructor
private final int MAX_P_GRUA; // a definir en el constructor
// canales para comunicación con el servidor y RPC
// uno por operacion (peticiones aplazadas)
private final Any2OneChannel chNotificarPeso;
private final Any2OneChannel chIncrementarPeso;
private final Any2OneChannel chNotificarSoltar;
private final Any2OneChannel chPrepararSustitucion;
private final Any2OneChannel chNotificarSustitucion;
// para aplazar peticiones de incrementarPeso
// esta va de regalo
private static class PetIncrementarPeso {
public int p;
public One2OneChannel chACK;
PetIncrementarPeso(int p) {
this.p = p;
this.chACK = Channel.one2one();
}
}
public ControlRecicladoCSP(int max_p_contenedor, int max_p_grua) {
// constantes del sistema
MAX_P_CONTENEDOR = max_p_contenedor;
MAX_P_GRUA = max_p_grua;
// creación de los canales
chNotificarPeso = Channel.any2one();
chIncrementarPeso = Channel.any2one();
chNotificarSoltar = Channel.any2one();
chPrepararSustitucion = Channel.any2one();
chNotificarSustitucion = Channel.any2one();
// arranque del servidor desde el constructor OJO!!!
new ProcessManager(this).start();
}
// interfaz ControlReciclado
// PRE: 0 < p < MAX_P_GRUA
// CPRE: self.estado =/= SUSTITUYENDO
// notificarPeso(p)
public void notificarPeso(int p) throws IllegalArgumentException {
// tratar PRE
if (p <= 0 || p > MAX_P_GRUA)
throw new IllegalArgumentException(new Exception("La grua ha colapsado"));
// PRE OK, enviar petición
chNotificarPeso.out().write(p);
}
// PRE: 0 < p < MAX_P_GRUA
// CPRE: self.estado =/= SUSTITUYENDO /\
// self.peso + p <= MAX_P_CONTENEDOR
// incrementarPeso(p)
public void incrementarPeso(int p) throws IllegalArgumentException {
// tratar PRE
if (p <= 0 || p > MAX_P_GRUA)
throw new IllegalArgumentException(new Exception("La grua ha colapsado"));
// PRE OK, creamos peticion para el servidor
PetIncrementarPeso peticion = new PetIncrementarPeso(p);
// enviamos peticion
chIncrementarPeso.out().write(peticion);
// esperar confirmacion
peticion.chACK.in().read();
}
// PRE: --
// CPRE: --
// notificarSoltar()
public void notificarSoltar() {
// enviar peticion
chNotificarSoltar.out().write(null);
}
// PRE: --
// CPRE: self = (_, sustituible, 0)
// prepararSustitucion()
public void prepararSustitucion() {
// enviar peticion
chPrepararSustitucion.out().write(null);
}
// PRE: --
// CPRE: --
// notificarSustitucion()
public void notificarSustitucion() {
// enviar peticion
chNotificarSustitucion.out().write(null);
}
// SERVIDOR
public void run() {
// estado del recurso
int pesoContenedor = 0;
Estado estado = Estado.LISTO;
int accediendo = 0;
// para recepción alternativa condicional
Guard[] entradas = { chNotificarPeso.in(), chIncrementarPeso.in(), chNotificarSoltar.in(),
chPrepararSustitucion.in(), chNotificarSustitucion.in() };
Alternative servicios = new Alternative(entradas);
// OJO ORDEN!!
final int NOTIFICAR_PESO = 0;
final int INCREMENTAR_PESO = 1;
final int NOTIFICAR_SOLTAR = 2;
final int PREPARAR_SUSTITUCION = 3;
final int NOTIFICAR_SUSTITUCION = 4;
// condiciones de recepción
final boolean[] sincCond = new boolean[5];
sincCond[NOTIFICAR_SOLTAR] = true;
sincCond[NOTIFICAR_SUSTITUCION] = true;
// creamos colección para almacenar peticiones aplazadas
Queue<PetIncrementarPeso> aplazadas = new LinkedList<PetIncrementarPeso>();
// bucle de servicio
while (true) {
// vars. auxiliares para comunicación con clientes
int pesoGrua;
PetIncrementarPeso peticion;
// actualización de condiciones de recepción cerrando los canales los cuales
// no cumplan las precondiciones necesarias para ejecutar su funcionalidad
sincCond[NOTIFICAR_PESO] = estado != Estado.SUSTITUYENDO;
sincCond[INCREMENTAR_PESO] = estado != Estado.SUSTITUYENDO;
sincCond[PREPARAR_SUSTITUCION] = estado == Estado.SUSTITUIBLE && accediendo == 0;
switch (servicios.fairSelect(sincCond)) {
case NOTIFICAR_PESO:
// estado != Estado.SUSTITUYENDO
// leer petición
pesoGrua = (int) chNotificarPeso.in().read();
// procesar petición
if (pesoGrua + pesoContenedor > MAX_P_CONTENEDOR) {
estado = Estado.SUSTITUIBLE;
} else {
estado = Estado.LISTO;
}
break;
case INCREMENTAR_PESO:
// leer peticion
peticion = (PetIncrementarPeso) chIncrementarPeso.in().read();
// tratar petición, y aplazar si no se cumple CPRE
// o aplazar directamente
if (peticion.p + pesoContenedor > MAX_P_CONTENEDOR) {
aplazadas.add(peticion);
} else {
pesoContenedor += peticion.p;
accediendo++;
peticion.chACK.out().write(null);
}
break;
case NOTIFICAR_SOLTAR:
// accediendo > 0 (por protocolo de llamada)
// leer peticion
chNotificarSoltar.in().read();
// tratar peticion
accediendo--;
break;
case PREPARAR_SUSTITUCION:
// estado == Estado.SUSTITUIBLE && accediendo == 0
// leer peticion
chPrepararSustitucion.in().read();
// tratar peticion
estado = Estado.SUSTITUYENDO;
break;
case NOTIFICAR_SUSTITUCION:
// estado == Estado.SUSTITUYENDO && accediendo == 0
// leer peticion
chNotificarSustitucion.in().read();
// tratar peticion
pesoContenedor = 0;
estado = Estado.LISTO;
break;
} // switch
// tratamiento de peticiones aplazadas
// Primero comprobamos que el estado sea distinto de sustituyendo, es decir, que
// realmente podremos desbloquear alguna peticion, en caso contrario simplemente
// avanzamos al final del bucle de servicio.
// Para ver si realmente podemos desbloquear alguna peticion cogemos la primera
// que haya en cola, si esta cumple las condiciones necesarias la tratamos, en
// caso contrario la ponemos de vuelta en la ultima posicion de la lista.
// Repetimos este proceso tantas veces como elementos hubiera en la lista al
// empezar el desbloqueo.
if (estado != Estado.SUSTITUYENDO) {
int i = 0;
int elementos = aplazadas.size();
while (i < elementos) {
peticion = aplazadas.poll();
if (peticion.p + pesoContenedor <= MAX_P_CONTENEDOR) {
pesoContenedor += peticion.p;
accediendo++;
peticion.chACK.out().write(null);
} else {
aplazadas.add(peticion);
}
i++;
}
}
// si estamos aqui es que no quedan peticiones
// aplazadas que podrian ser atendidas!!!!!!!!!!!!!!!!!!
} // bucle servicio
} // run() SERVER
} // class ControlRecicladoCSP