El problema del almacen automatizado describe una situación habitual en la gestión de recursos: se cuenta con un número limitado de recursos disponibles (6 piezas), que en algún momento pueden agotarse. Llegado a este punto los usuarios de los recursos (operarios) quedan a la espera de que se recargue el sistema con nuevos recursos, operación que se considera costosa. Como en este caso se tienen varios tipos de recursos (piezas A, B, C y D) y son solicitados de forma individual (de uno en uno), la gestión del sistema debe hacerse de tal forma que la recarga de un tipo de recurso, por ser como se ha dicho una operación costosa, no impida que puedan realizarse otra peticiones. Para ello, se delega en otro proceso la actividad de recargar (en este caso el Robot) que será el encargado de ir a por más piezas del tipo solicitado.
Finalmente, constatar que la gestión de las piezas puede realizarse de forma totalmente distribuida, puesto que los recursos (las piezas) son perfectamente distinguibles y su gestión independiente.
A continuación se presenta un programa en CcModula que resuelve el problema propuesto. Obsérvese que sólo ha sido necesario implementar un proceso Pieza, hacindo instancias a través de su parámetro de los diferentes tipos de piezas que se gestionan.
< C W > MODULE AlmacenMecanico; FROM CCWindow IMPORT Clear; FROM CCInOut IMPORT WriteCard, WriteString, WriteLn, ReadCard, Retardo; CONST NumOperarios = 10; TYPE TipoPieza = (piezaA, piezaB, piezaC, piezaD); TipoSenyal = CARDINAL; VAR peticionPieza : ARRAY [piezaA .. piezaD] OF CHANNEL (* OF TipoSenyal *); recibePiezas : ARRAY [piezaA .. piezaD] OF CHANNEL (* OF TipoSenyal *); avisarRobot : CHANNEL; I : CARDINAL; P : TipoPieza; TASK Pieza (tipo : TipoPieza); VAR piezasQuedan : CARDINAL; senyal : TipoSenyal; BEGIN GetChannel (peticionPieza [tipo]); GetChannel (recibePiezas [tipo]); piezasQuedan := 6; LOOP SELECT WHEN (piezasQuedan > 0), Receive (peticionPieza [tipo], senyal) DO DEC (piezasQuedan); IF (piezasQuedan = 0) THEN Send (avisarRobot, tipo) END (* IF *) WHEN Receive (recibePiezas [tipo], senyal) DO piezasQuedan := 6; END (* SELECT *) END (* LOOP *) END Pieza; TASK Robot; VAR tipo : TipoPieza; senyal : TipoSenyal; BEGIN GetChannel (avisarRobot); LOOP Receive (avisarRobot, tipo); << Ir al almacen a por una batea de piezas del tipo "tipo" >> Send (recibePiezas[tipo], senyal); END (* LOOP *) END Robot; TASK Operario (id : CARDINAL ); VAR tipo : TipoPieza; senyal : TipoSenyal; BEGIN LOOP << Determinar el "tipo" de pieza que se quiere >> Send (peticionPieza [tipo], senyal); END (* LOOP *) END Operario; BEGIN COBEGIN Robot; FORALL P:= piezaA TO piezaD DO Pieza (P) END; (* FORALL *) FORALL I:=1 TO NumOperarios DO Operario (I) END (* FORALL *) COEND END AlmacenMecanico.
Una solución alternativa para implementar los procesos Pieza pasa por ``percatarse'' de que no es necesario mantener una instrucción SELECT y que puede resolverse con recepciones deterministas, como sigue:
TASK Pieza (tipo : TipoPieza); VAR piezasQuedan : CARDINAL; senyal : TipoSenyal; BEGIN GetChannel (peticionPieza [tipo]); GetChannel (recibePiezas [tipo]); piezasQuedan := 6; LOOP Receive (peticionPieza [tipo], senyal); DEC (piezasQuedan); IF (piezasQuedan = 0) THEN Send (avisarRobot, tipo); Receive (recibePiezas [tipo], senyal) DO piezasQuedan := 6; END (* IF *) END (* LOOP *) END Pieza;