next up previous
Next: Gestione delle risorse condivise Up: Parte VI: creiamo un Previous: Il thread per il


Il thread per il ciclo ``leggi-invia-leggi'' dei messaggi

Il thread per la gestione del ciclo LIL per un certo user può essere attivato contestualmente all'aggiunta dello user nella chat room (metodo addUser di ChatRoom) e terminare alla rimozione dello user dalla chat room (metodo removeUser di ChatRoom).

Il ciclo LIL ha il compito di controllare continuamente il MessageBox del suo client ed inviare i messaggi in esso inseriti dai cicli REIR di altri client (si veda la Figura 5).

Figure: Interazione dei thread tra interfaccia grafica del client e del server.
Image /~baldoni/didattica/aa0203/ProgInRete/ProgettoLabPiR0203/Immagini/socket_connection_small.png
Se non vi sono messaggi in coda il thread che gestisce il ciclo LIL deve essere messo in attesa dell'inserimento di un messaggio. A tale fine è necessario modificare il metodo readMessage di MessageBox introducento una wait():
public synchronized Message readMessage() throws InteruptedException {
    while (box.isEmpty()) wait();
    // operazione di lettura
}
Il thread è svegliato non appena un messaggio viene inserito nella coda di messaggi. A tale fine è necessario modificare il metodo writeMessage di MessageBox:
public synchronized void writeMessage(Message message) {
    // operazione di scrittura
    notifyAll();
}

Per ogni oggetto MessageBox presente nella chat room è quindi necessario attivare un thread contenente il ciclo LIL, si definisca quindi una classe MessageBoxWithThreadLIL che estende MessageBox ed implementa Runnable contenente i campi:

Si faccia riferimento alla Sezione 3.1 per uno schema dettagliato della classe MessageBoxWithLIL. In particolare, questa classe deve ridefinire il metodo run che rappresenta il ciclo LIL vero e proprio:
public void run() {
    while (!stopRequested)
        try {
           // leggi un messaggio del controllato messageBox 
           // e invialo al client
           out. writeObjet(this.readMessage());
        }
        catch (InterruptedException err) {
            if (stopRequested)
                return;
        }
}
Si noti che in effetti il comando ReceiveCRC non è utilizzato nella soluzione suggerita, si è liberi di trovare soluzioni alternative se lo si desidera.

Infine è necessario modificare il metodo addUser al fine di creare un oggetto di tipo MessageBoxWithThreadLIL anzichè un semplice MessageBox:

public void addUser(User user, ObjectOutput out) {
    synchronized(listOfMessageBox) {  
        MessageBox mb = new MessageBoxWithThreadLIL(user, out);
        // aggiunta di mb in listOfMessageBox
    }    
}
Si noti che lo stream di output di oggetti out può essere passato al metodo addUser attraverso il parametro opzionale del metodo execCRC del comando GetIntoRoomCRC dove la addUser è invocata. Cioè lo schema del metodo run della classe ThreadREIR dovrebbe diventare:
public void run() {
    boolean stopRequested = false;
    Message message;
    ChatRoomCommand command;
    while (!stopRequested) {
        // leggi un comando da `in'
        if (comando instaceof GetIntoRoomCRC)
            message = comando.execCRC(chatRoom, out);
        else
            message = comando.execCRC(chatRoom, null);
        // scrivi message su `out'
        if (comando instanceof ExitRoom) stopRequested = true;
    }
}

In modo analogo la rimozione di uno user deve prevvedere anche all'interruzione dell'esecuzione del thread attivo presso un MessageBox:

public void removeUser(User user) {
    synchronized(listOfMessageBox) {  
        MessageBoxWithThreadLIL mb;
        // cerca la casella di user e ponila in mb
        mb.requestedStop();
        // rimuovi la casella di user da listOfMessageBox
    }    
}


next up previous
Next: Gestione delle risorse condivise Up: Parte VI: creiamo un Previous: Il thread per il
Baldoni Matteo 2003-05-08