Messages entre objets de classe differente

Pour echanger des messages entre objets de classe differentes, on ne peut plus avoir recours au mecanisme precedent de memoire partagee.

Dans l'exemple qui suit, on va declarer un objet (classe Canal) qui autorise des communication qui ont les proprietes suivantes :
  • bidirectionnelles,
  • asychrones bufferisees.

Un canal est partage par deux processus qui doivent s'identifier lors de l'etablissement de la connexion. La connexion peut etre relachee et le canal redevient libre pour une autre.

Applet :

Programme (classe Canal) :

class Canal

{

    private StringBuffer msg[] ;

    private boolean ok_lit[], ok_ecrit[] ;

    private int port[] ;

    private int port1, port2 ;

    private com2 mon_pere ;

    Canal(com2 pere)

    {

      mon_pere = pere ;

      msg = new StringBuffer[2] ;

      ok_ecrit = new boolean[2] ;

      ok_ecrit[0] = true ; ok_ecrit[1] = true ;

      ok_lit = new boolean[2] ;

      ok_lit[0] = false ; ok_lit[1] = false ;

      port = new int[2] ; port1 = -1 ; port2 = -1 ;

    }

    public void init(int le_port)

    {

      if (le_port != -1)

        if (port1 == -1)

          port1 = le_port ;

        else

          if (port2 == -1) port2 = le_port ;

          else mon_pere.erreur(new StringBuffer("Classe canal : tous les ports sont pris.")) ;

      else mon_pere.erreur(new StringBuffer("Classe canal : numero de port = -1 !")) ;

    }

    public void libere(int le_port)

    {

      if (port1 == le_port) port1 = -1 ;

      else

        if (port2 == le_port) port2 = -1 ;

        else mon_pere.erreur(new StringBuffer("Classe canal : liberation de port inconnu.")) ;

    }

    public boolean ecrit_ok(int le_port)

    {

      if (port1 == le_port) return(ok_ecrit[0]) ;

      else

        if (port2 == le_port) return(ok_ecrit[1]) ;

        else mon_pere.erreur(new StringBuffer("Classe canal, ecrit_ok : port inconnu.")) ;

      return(false) ;

    }

    public boolean lit_ok(int le_port)

    {

      if (port1 == le_port ) return(ok_lit[0]) ;

      else

        if (port2 == le_port) return(ok_lit[1]) ;

        else mon_pere.erreur(new StringBuffer("Classe canal, lit_ok : port inconnu.")) ;

      return(false) ;

    }

    public void ecrit(int le_port, StringBuffer message)

    {

      if (port1 == le_port)

      { ok_ecrit[0] = false ; msg[0] = new StringBuffer(message.toString() ) ; ok_lit[0] = true ; }

      else

      {

        if (port2 == le_port)

        { ok_ecrit[1] = false ; msg[1] = new StringBuffer(message.toString() ) ; ok_lit[1] = true ; }

        else mon_pere.erreur(new StringBuffer("Classe canal, ecrit : port inconnu.")) ;

      }

    }

    public StringBuffer lit(int le_port)

    {

      if (port2 == le_port)

      { ok_lit[0] = false ; ok_ecrit[0] = true ; return(msg[0]) ; }

      else

      {

        if (port1 == le_port)

        { ok_lit[1] = false ; ok_ecrit[1] = true ; return(msg[1]) ; }

        else mon_pere.erreur(new StringBuffer("Classe canal, lit : port inconnu.")) ;

      }

      return(new StringBuffer("Erreur")) ;

    }

}

Programme (corps des processus legers) :

class Message1 extends Thread

{

    private StringBuffer mon_nom ;

    com2 mon_pere ; // on a besoin d'une reference de l'applet pour ecrire

    int mon_numero ;

    boolean ok ; // va servir a bloquer le processus avant de lancer le traitement

    private final int je_suis_du_type1 = 1 ;

    private Canal chan ;

    Message1(com2 pere, StringBuffer nom, int num, Canal channel)

    {

      super() ;

      ok = false ; mon_numero = num ;

      mon_nom = new StringBuffer(nom.toString()) ;

      mon_pere = pere ;

      chan = channel ;

      chan.init(mon_numero) ;

    }

    // run est le corps du processus

    public void run()

    {

      int i, j, k ; StringBuffer lu ;

      while (! ok) // attente bloquante pour laisser la main a l'applet

      { try { sleep(500) ; } catch (InterruptedException e) {} }

      k = 0 ;

      while (k<10)

      {

        for (i=0 ; i<3 ; i++)

        {

          if (chan.ecrit_ok(mon_numero) )

          {

            chan.ecrit(mon_numero,new StringBuffer(mon_nom + " " + i)) ;

            mon_pere.qui_est_actif(new StringBuffer(mon_nom + " ecrit.")) ;

          }

          yield() ;

          if (chan.lit_ok(mon_numero) )

          {

            lu=new StringBuffer(chan.lit(mon_numero).toString() ) ;

            mon_pere.qui_est_actif(new StringBuffer(mon_nom + " a lu : " + lu)) ;

            }

          yield() ;

        }

        try { sleep(500) ; } catch (InterruptedException e) {}

      }

      chan.libere(mon_numero) ;

    }

    public void dit_ok()

    { ok = true ; }

}

Programme (de l'applet) :

public class com2 extends Applet //implements Runnable

{

    protected final int NB_PROC=2 ;

    protected Message1 p1 ;

    protected Message2 p2 ;

    protected Canal chan ;

    protected int combien, ligne ;

    protected StringBuffer message ;

    protected Graphics gc ;

    protected boolean deja_lance ;

    public void init()

    {

      chan = new Canal(this) ;

      p1 = new Message1(this, new StringBuffer("Processus P1"), 1, chan ) ;

      p2 = new Message2(this, new StringBuffer("Processus P2"), 2, chan ) ;

      gc = getGraphics() ; deja_lance = false ;

    }

    ../..

}

NB : Ici aussi, la classe Canal peut etre amelioree en permettant d'ecrire les messages dans une file d'attente par exemple.


Ph. RIS 1997