Come risolvere un problema di coda di eventi in un emulatore di computer in Java

3

Sto scrivendo un emulatore di basso livello (in Java) dell'IBM 1620, un computer di fine anni '50. Con "livello basso" intendo che l'unità di lavoro osservabile più bassa è il "trigger" da 20 microsecondi - le istruzioni della macchina raggiungono i loro obiettivi eseguendo una serie di questi trigger; e ho scritto codice per emularli quasi tutti. Con "osservabile" intendo che la console del 1620 conteneva un tasto "Single Cycle Execution" che permetteva di far avanzare manualmente un trigger alla volta e la maggior parte dello stato interno della CPU (registri, PC, condizioni) venivano visualizzati su una grande console di luci. Garantisco la correttezza dello stato a livello di singolo ciclo.

Normalmente l'emulatore è in attesa che l'operatore preme START, o è nel suo ciclo di esecuzione principale, eseguendo il trigger dopo l'attivazione. Deve anche essere in grado di rispondere a eventi esterni come un interruttore a levetta, o la suddetta chiave Single Cycle Execution, che vengono trasmessi al thread CPU dal thread GUI da una coda di eventi. Il ciclo di esecuzione fa capolino in questa coda prima di sparare il prossimo trigger, e finora questo ha funzionato bene.

Ora, tuttavia, sto implementando le istruzioni I / O del lettore di schede e ho un problema. Tutti i 1620 I / O erano sincroni (il 1620 non aveva capacità di interruzione), quindi quando eseguiva l'istruzione ReadCard, avrebbe letteralmente atteso a metà trigger fino a quando il lettore di schede non consegnava una scheda. Questo normalmente richiedeva un decimo di secondo, a meno che l'operatore non avesse montato il mazzo di carte ! È quest'ultima contingenza che crea il problema: il 1620 deve attendere a metà trigger (cioè il ciclo di esecuzione principale non è in esecuzione), rimanendo comunque reattivo a eventi esterni (interruttori lanciati, tasto Reset o, ovviamente, una scheda da il lettore di schede).

Non riesco a pensare a un modo pulito ed elegante per progettare questo. Il polling e la gestione degli eventi "non richiesti" all'inizio del ciclo di esecuzione hanno funzionato bene finora, ma ora ho bisogno di un meccanismo chiamabile che faccia la stessa cosa ma sia in grado di restituire il controllo al chiamante quando si verifica l'evento giusto. Ecco come appare adesso:

state:
    MANUAL means unable to immediately process next trigger
    AUTO means we can go ahead and process next trigger

do forever {
    processQueuedEvents()  // event-processing never blocks
    if (state == MANUAL) {
       waitForEvents()     // this blocks until queue not empty
    } else {               // state == AUTO
       trigger = doTrigger(trigger) // run trigger and get next one
    }
}

Trigger CPU E30 invia un messaggio a CardReader che richiede un buffer di scheda e deve attendere per ricevere l'evento contenente il buffer. Nel frattempo, la CPU deve continuare a ricevere ed elaborare gli eventi come al solito.

Potrei immaginare che questo sia un problema di progettazione del sistema operativo, ma non è il mio strong motivo. Qualcuno può fornire una guida?

    
posta Chap 22.07.2011 - 06:45
fonte

2 risposte

1

Heh, che interessante. Il tuo problema è come simulare un meccanismo meno efficiente. Penso che puoi ottenere l'effetto che stai cercando avviando un thread di lavoro per recuperare il file. Quindi chiama semplicemente waitFor () per fare in modo che il simulatore attenda il ritorno.

Per simulare l'attesa, puoi utilizzare un timer prima di recuperare il file e, una volta terminata l'operazione, controlla e verifica se hai già superato i 10 millisecondi. In questo caso, hai finito, altrimenti, interrompi il timer e forza la tua applicazione ad attendere il tempo rimanente prima di restituire i risultati.

Se lo fai correttamente, dovresti essere in grado di chiamare un metodo che recupera in modo sincrono i dati dei file in non meno di 10 millisecondi. Questo aiuto?

    
risposta data 22.07.2011 - 14:17
fonte
0

Avvia la funzione 'trigger' se non può fare ulteriori progressi in avanti. Quindi torna ad attendere gli eventi e cosa no. Non appena qualcosa cambia, vedi se la funzione 'trigger' può avanzare ulteriormente. Non bloccare la funzione 'trigger', blocca la funzione 'wait for anything to happen'.

    
risposta data 13.08.2011 - 20:54
fonte

Leggi altre domande sui tag