Next: About this document Up: Almacén automatizado Previous: Almacén automatizado

## Almacén automatizado (SOLUCIÓN)

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;