Initial commit
[amiga/OpenBoopsi.git] / docs / Intuition
1
2 INDICE
3
4 Introduzione
5    Come si comporta Intuition
6    Come si comporta MUI
7
8 Problemi
9    Problema n. 1 (input.device bloccato; Intuition)
10    Problema n. 2 (refresh della GUI bloccato; MUI)
11
12 Ipotesi di soluzioni
13    Possibile soluzione per il problema n. 1 (sotto-task IDCMP in parallelo)
14    Possibile soluzione per il problema n. 2 (classe MUI con task asincrono)
15
16 Considerazioni finali
17    Funzionamento seriale dell'input.device
18    Fattibilità di un patch per Intuition
19
20
21 INTRODUZIONE
22
23 Come si comporta Intuition
24 --------------------------
25
26 L'input dell'utente viene letto, comunicando direttamente con l'hardware,
27 da keyboard.device e gameport.device, che lo trasmettono all'input.device.
28
29 Quest'ultimo unisce le diverse informazioni sull'input in un unico stream
30 (flusso) di "eventi di input", omogeneo e sequenziale, rappresentato con
31 una lista di strutture InputEvent.
32
33 L'input.device passa poi tale lista ad una serie di "input handler", secondo
34 un ordine basato sulla loro priorità.
35
36 Ciascun handler può intraprendere delle azioni in base al contenuto della
37 lista ricevuta in ingresso; può inoltre apporre modifiche alla lista stessa
38 aggiungendo, rimuovendo o alterando eventi. In uscita l'handler restituisce
39 la lista modificata, la quale diventerà l'ingresso per l'handler successivo.
40
41 Il codice di un handler viene eseguito come una normale chiamata a funzione:
42 di conseguenza esso gira sempre nel contesto del task dell'input.device.
43
44 Normalmente l'handler con priorità massima è quello della commodities.library
45 (che quindi intercetta gli eventi prima di chiunque altro), tranne che nel
46 caso in cui essa non sia stata ancora aperta.
47
48 L'handler immediatamente successivo è tipicamente quello di Intuition; la
49 sua funzione è "interpretare", ed eventualmente filtrare, tutti quegli eventi
50 che possono influire sullo stato della GUI o sulle attività dei programmi che
51 ne fanno uso.
52
53 Questo handler fondamentalmente si limita a chiamare la funzione Intuition()
54 della intuition.library, passandole come unico argomento il puntatore alla
55 lista di eventi ricevuto in ingresso.
56
57 Intuition() verifica la natura di ogni singolo evento e, se necessario,
58 reagisce ad esso eseguendo opportune azioni, come ad esempio attivare una
59 finestra, modificare l'aspetto e lo stato di un gadget o inviare un messaggio
60 ad un applicativo.
61
62 La casistica più comune comprende:
63
64 · Refresh automatico di una componente della GUI (bordo di una finestra,
65   gadget non BOOPSI, barra del titolo di uno schermo).
66
67 · Visualizzazione di menu
68
69 · Invocazione dell'opportuno metodo di un gadget BOOPSI
70
71 · Nessuna azione visibile (es.: click all'interno di una finestra, ma non
72   su un gadget)
73
74 A ciascuna di queste azioni può essere associato l'invio di un particolare
75 messaggio, rappresentato da una struttura IntuiMessage, all'applicativo
76 "proprietario" della finestra correntemente attiva (normalmente il task che
77 l'ha aperta).
78
79 Gli IntuiMessage hanno spesso una corrispondenza stretta con gli InputEvent
80 da cui derivano.
81
82 Al termine di queste azioni gli eventi che non possono essere utili agli
83 handler successivi vengono rimossi dalla lista, altri (generalmente utili
84 a console.device) vengono aggiunti, e la funzione Intuition() termina
85 restituendo all'handler il puntatore alla nuova lista.
86
87 Infine l'handler di Intuition restituisce a sua volta il puntatore
88 all'input.device che può quindi passarlo all'handler successivo, solitamente
89 quello di console.device.
90                                                                _ _ _ _ _ _
91                                                               | \ \ \ \ \ |
92                                                               |Applicativo|
93                                                               |_\_\_\_\_\_|
94                                InputEvent stream                   /|\
95                              .····················.            _ _ _|_ _ __
96                              :                    :           |            |
97  _ _ _ _ _ _ _ _        _ _ _: _ _ _     _ __ _ _ V _ _ __ _  |Messaggio ad|
98 |               |      |            |   |                   | |applicativo |
99 |keyboard.device|-.    |            |==>|Input handler (CX) | |__ _ _ _ _ _|
100 |_ _ _ _ _ _ _ _|  \   |            |   |_ _ _ _ _ _ _ _ _ _|      /\
101  _ _ _ _ _ _ _ _    \  |            |    _ __ _ _ V _ _ __ _     _ ||_ _ _ _
102 |               |    \ |input.device|   |                   |   |           |
103 |gameport.device|----->|    task    |==>|Input handler (I)  |==>|Intuition()|
104 |_ _ _ _ _ _ _ _|    / |            |   |_ _ _ _ _ _ _ _ _ _|   |_ _ _ _ _ _|
105  _ _ _ _ _ _ _ _    /  |            |    _ __ _ _ V _ _ __ _       ||
106 |               |  /   |            |   |                   |  _ _ \/_ _
107 | timer.device  |-'    |            |==>|Input handler (c.d)| |         |
108 |_ _ _ _ _ _ _ _|      |__ _ _ _ _ _|   |_ _ _ _ _ _ _ _ _ _| |Refresh  |
109                                                   :           |della GUI|
110                                                  _:           |_ _ _ _ _|
111                                                 / \_/              ||
112                                                   :        _ _ _ _ \/_ _ _ _
113                                                   :       |                 |
114                                                   V       |Esecuzione metodo|
115                                                 /////     |_ _ _ _ _ _ _ _ _|
116
117 Questo meccanismo comporta che l'unico codice eseguito nel contesto di un
118 applicativo che faccia uso di Intuition è quello che si occupa di rispondere
119 agli IntuiMessage ed intraprendere eventuali azioni in base al loro contenuto
120 (generalmente finalizzate a svolgere il compito richiesto dall'utente più
121 che a gestire l'interfaccia; tuttavia nel caso di GadTools alcune operazioni
122 di gestione della GUI vengono affidate al task dell'applicativo mediante le
123 funzioni GT_GetIMsg() e GT_ReplyIMsg()).
124
125 In particolare, nel caso dei gadget BOOPSI, la risposta della GUI risulta
126 sempre immediata e "in tempo reale", indipendentemente dalle operazioni che
127 l'applicativo sta svolgendo nello stesso momento, poiché di fatto se ne
128 occupa asincronamente un altro task (quello dell'input.device).
129
130
131 Come si comporta MUI
132 --------------------
133
134 La differenza fondamentale tra MUI ed Intuition è che i suoi gadget, pur
135 essendo oggetti BOOPSI, sono sottoclassi di "rootclass" piuttosto che di
136 "gadgetclass". Di conseguenza non sono riconosciuti da Intuition come dei
137 normali gadget e non vengono quindi gestiti automaticamente dalla funzione
138 Intuition(). Tutto ciò che quest'ultima rileva quando l'utente interagisce
139 con i gadget MUI è una serie di eventi IDCMP_MOUSEBUTTONS e IDCMP_MOUSEMOVE
140 che essa trasmette, invariati, al task proprietario della finestra.
141
142 Quest'ultimo tipicamente si trova in uno stato di attesa degli eventi.
143 Per ogni evento ricevuto chiama una funzione MUI di gestione dell'input
144 (per l'esattezza invoca un metodo di una particolare classe) la quale
145 è poi in grado di determinare a quale gadget MUI va passato, mediante
146 l'invocazione di un suo opportuno metodo, l'evento appena letto.
147                                                         _ _ _ _ _ _ _ _ _ __
148                                                        | \ \ \ \ \ \ \ \ \ \|
149                                                        |Operazioni programma|
150                                                        |_\_\_\_\_\_\_\_\_\_\|
151                  _ _ _ _ _ _ _ _ __                               /\
152  _ _ _ _ _ _    |                  |      _ _ _ _ _ _      _ _ _ _|| _ _ _ _
153 |           |   |Semplice messaggio|     | \ \ \ \ \ |    | \ \ \ \ \ \ \ \ |
154 |Intuition()|==>| all'applicativo  |---->|Applicativo|    |Refresh della GUI|
155 |_ _ _ _ _ _|   | (IDCMP_MOUSE#?)  |     |_\_\_\_\_\_|    |_\_\_\_\_\_\_\_\_|
156                 |__ _ _ _ _ _ _ _ _|          ||                  /\
157                                         _ _ _ \/_ _ __     _ _ _ _|| _ _ _ _
158                                        | \ \ \ \ \ \ \|   | \ \ \ \ \ \ \ \ |
159                                        |Gestione input|==>|Esecuzione metodo|
160                                        |_\_\_\_\_\_\_\|   |_\_\_\_\_\_\_\_\_|
161
162 Con MUI, di conseguenza, la risposta della GUI (almeno con le classi di
163 gadget standard fornite con il pacchetto) risulta sincrona alle operazioni
164 del task dell'applicativo, in quanto avviene nel suo stesso contesto.
165
166
167 PROBLEMI
168
169 Problema n. 1 (input.device bloccato; Intuition)
170 ------------------------------------------------
171
172 La gestione dell'input secondo il modello di Intuition, cioè tramite un
173 handler, ha il vantaggio di garantire pressoché sempre una risposta immediata
174 da parte della GUI, anche nel caso in cui l'applicativo non fosse pronto a
175 reagire all'input ricevuto.
176
177 Tuttavia, poiché l'handler di Intuition opera sempre, come già illustrato,
178 nel contesto dell'input.device, qualsiasi trasmissione di eventi di input
179 nel sistema risulta completamente bloccata fino alla conclusione delle sue
180 operazioni.
181
182 Il problema si manifesta in modo evidente soprattutto con i gadget BOOPSI;
183 infatti l'handler invoca opportuni metodi di tali gadget quando l'input
184 dell'utente è diretto a loro o comporta una modifica del loro stato. Nel
185 caso di metodi particolarmente complessi, come quelli dei gadget associati
186 ai DataType, il tempo di esecuzione può essere elevato, e di conseguenza
187 la trasmissione dell'input nell'intero sistema può subire una sospensione di
188 durata non trascurabile.
189
190 Il sintomo più tipico è il blocco del puntatore del mouse, ma anche altre
191 attività del sistema operativo che si basino su una regolare ricezione di
192 eventi di input (ad esempio quelli generati dal timer.device) rischiano di
193 venire ostacolate con conseguenze imprevedibili.
194
195
196 Problema n. 2 (refresh della GUI bloccato; MUI)
197 -----------------------------------------------
198
199 Il sistema MUI presenta un problema per certi versi opposto, ma ugualmente
200 fastidioso per l'utente. Con i gadget di MUI le operazioni svolte nel
201 contesto del task dell'input.device sono sempre molto limitate e di breve
202 durata; si tratta per lo più di comunicare una serie di click dei pulsanti
203 del mouse (e spostamenti di quest'ultimo) all'applicativo associato al canale
204 IDCMP della finestra attiva.
205
206 Ogni operazione relativa alla GUI viene poi effettuata nel contesto del task
207 che riceve i messaggi in questione. Nel caso esso sia occupato in qualche
208 elaborazione e quindi non si trovi in attesa di segnali dalla porta IDCMP,
209 come è facile immaginare, nessun tipo di aggiornamento della GUI verrà
210 attuato fino alla conclusione delle operazioni.
211
212 L'utente, in questo caso, non osservando alcuna risposta dai gadget con cui
213 tenta di interagire, può avere l'impressione che l'intero programma sia
214 bloccato e non semplicemente impegnato in altre attività.
215
216 Nel caso migliore l'utente si fa una cattiva opinione del programma; inoltre
217 l'incertezza sul da farsi può portare l'utente a danneggiare inavvertitamente
218 il lavoro che sta svolgendo mediante l'applicativo. Ad esempio, un tentativo
219 di selezione ripetuta dello stesso gadget (nella speranza di una ripresa del
220 funzionamento del programma) può provocare effetti collaterali indesiderati
221 nell'istante in cui l'applicativo ricomincia a gestire l'input e si occupa di
222 quello nel frattempo ricevuto.
223
224
225 IPOTESI DI SOLUZIONI
226
227 Possibile soluzione per il problema n. 1 (sotto-task IDCMP in parallelo)
228 ------------------------------------------------------------------------
229
230 Una possibile soluzione al primo problema, attuabile al livello di Intuition,
231 è la gestione multithreaded degli eventi di input trasmessi al suo handler
232 dall'input.device, che in tal modo si libererebbe molto rapidamente dopo
233 la chiamata alla funzione Intuition(). Come realizzare questo nella pratica?
234
235 Un'idea potrebbe essere associare ad ogni schermo e finestra un task
236 dedicato, creato all'apertura ed eliminato alla chiusura. Ciascuno di questi
237 task riceverebbe solo gli eventi che lo riguardano e potrebbe gestirli del
238 tutto asincronamente al resto del sistema e in particolare all'input.device.
239
240 Per rendere possibile ciò sarebbe necessario apportare alcune modifiche alla
241 funzione Intuition():
242
243 1. Essa dovrebbe, preliminarmente, esaminare la lista di InputEvent ricevuta
244    dall'input.device e in base ad essa costruire una seconda lista privata
245    copiando tutti gli eventi che riguardano la GUI.
246
247 2. Fatto ciò, tutti gli eventi che non devono essere rilevati dagli altri
248    handler dovrebbero essere rimossi dalla lista principale.
249
250 3. La lista privata di eventi dovrebbe poi essere separata in sottoliste,
251    ognuna indirizzata all'opportuna finestra (o all'opportuno schermo).
252
253 4. Ogni sottolista dovrebbe essere spedita, tramite un opportuno messaggio,
254    al task associato alla finestra (o schermo) destinazione.
255
256 5. A questo punto Intuition() potrebbe terminare subito la sua esecuzione,
257    senza aspettare alcuna risposta dai task a cui ha spedito i messaggi;
258    in questo modo l'input.device sarebbe subito libero di proseguire la
259    sua attività.
260
261 Una possibile variante è il passaggio (subito dopo il punto 2) della lista
262 privata ad un task "intermedio" che si occupi di eseguire le operazioni
263 rimanenti; in questo caso Intuition() potrebbe terminare prima del punto 3.
264 Questo ipotetico task intermedio potrebbe ad esempio venire creato in modo
265 automatico all'apertura della intuition.library.
266
267 Occorre prestare molta attenzione all'implementazione del punto 2, in quanto
268 è necessario stabilire delle regole precise in base alle quali si possa
269 determinare IN ANTICIPO e senza ambiguità se un evento riguarda o no la GUI e
270 se esso debba venire trasmesso o no ai successivi handler. Questo potrebbe,
271 oggettivamente, non essere un compito facile.
272
273 In particolare, se un evento deve essere modificato da Intuition e poi
274 trasmesso al resto degli handler, bisogna che:
275
276 - Si sappia già come modificarlo PRIMA di passarlo al task destinatario,
277   per non dover aspettare che questo termini fornendo informazioni sulla
278   modifica da effettuare (soluzione non sempre applicabile), oppure
279
280 - Il task destinatario, dopo avere modificato personalmente l'evento, si
281   occupi di REINSERIRLO nella catena di InputEvent a monte dell'handler di
282   Intuition. Questo si può realizzare ad esempio aggiungendolo ad una coda
283   di eventi globale periodicamente letta dall'handler, oppure sfruttando
284   la commodities.library. Non basta chiamare direttamente Intuition() con
285   l'evento in questione poiché si rimarrebbe nel contesto del task.
286   Le regole per realizzare ciò potrebbero risultare abbastanza complicate.
287
288 Ammettendo di risolvere questi problemi, restano da esaminare i compiti dei
289 singoli task destinatari.
290
291 Quelli associati alle finestre svolgerebbero esattamente gli stessi compiti
292 che attualmente sono svolti dalla funzione Intuition(), cioè aggiornare lo
293 stato della GUI, invocare opportuni metodi di eventuali gadget BOOPSI
294 selezionati e spedire IntuiMessage all'applicativo che "possiede" la finestra
295 (con l'unica avvertenza, ovvia del resto, di assicurarsi che il task sia
296 completamente rientrante ed esegua una corretta arbitrazione sui dati globali
297 di IntuitionBase).
298
299 I task associati agli schermi non dovrebbero fare altro che gestire la
300 selezione degli unici due possibili gadget, quello di trascinamento e quello
301 di profondità, nonché la disattivazione di tutte le finestre in caso di
302 click del mouse su una zona libera dello schermo, l'autoscrolling e lo screen
303 dragging tramite Amiga sinistro + mouse.
304
305 Si potrebbe anche pensare ad un ulteriore task indipendente che gestisca
306 semplicemente il movimento del puntatore, ma questo è un compito talmente
307 banale che potrebbe essere svolto direttamente (e più rapidamente) dalla
308 funzione Intuition().
309                                                            _ _ _ _ _ _
310                                                           | \ \ \ \ \ |
311                                                           |Applicativo|
312                                                           |_\_\_\_\_\_|
313         InputEvent stream                                      /|\
314       .····················.                                    |
315       :                    :                             ::::::::::::::::
316  _ _ _: _ _ _     _ __ _ _ V _ _ __ _                    ::Messaggio ad::
317 |            |   |                   |                   ::applicativo:::
318 |            |==>|Input handler (CX) |                   ::::::::::::::::
319 |            |   |_ _ _ _ _ _ _ _ _ _|                          /\
320 |            |    _ __ _ _ V _ _ __ _     _ _ _ _ _ _           ||
321 |input.device|   |                   |   |           |   :::::::::::::::::
322 |    task    |==>|Input handler (I)  |==>|Intuition()|-->::Task finestra::
323 |            |   |_ _ _ _ _ _ _ _ _ _|   |_ _ _ _ _ _|   :::::::::::::::::
324 |            |    _ __ _ _ V _ _ __ _                           ||
325 |            |   |                   |                          \/
326 |            |==>|Input handler (c.d)|                     :::::::::::::
327 |__ _ _ _ _ _|   |_ _ _ _ _ _ _ _ _ _|                     ::Refresh::::
328                            :                               ::della GUI::
329                           _:                               :::::::::::::
330                          / \_/                                  ||
331                            :                                    \/
332                            :                           :::::::::::::::::::::
333                            V                           ::Esecuzione metodo::
334                          /////                         :::::::::::::::::::::
335
336
337 Per concludere, si può osservare che in realtà sarebbe abbastanza raro che
338 la stessa lista contenga eventi indirizzati a finestre diverse; l'utente,
339 in circostanze normali, non dovrebbe essere più veloce dell'elaborazione
340 dell'input da parte del sistema. Un'eccezione sono gli eventi di timer (che
341 non sono generati dall'utente e sono sempre diretti a tutte le finestre).
342
343 Alla luce di questa considerazione si potrebbe pensare di lasciare al
344 programmatore (o addirittura all'utente) la facoltà di decidere quali
345 finestre debbano essere dotate di un task IDCMP dedicato, e quali invece
346 possano semplicemente appoggiarsi ad un task IDCMP globale.
347
348
349 Possibile soluzione per il problema n. 2 (classe MUI con task asincrono)
350 ------------------------------------------------------------------------
351
352 Il problema di MUI potrebbe risolversi molto facilmente con una riscrittura
353 delle classi di base del sistema.
354
355 L'idea è che il dispatcher di un gadget MUI non dovrebbe eseguire in sequenza
356 (e nel contesto dell'applicativo) il refresh della GUI e poi la chiamata alla
357 funzione di callback associata al gadget.
358
359 Ogni istanza di una classe di gadget MUI dovrebbe avere un proprio task
360 privato a cui affidare la chiamata alla funzione di callback, rendendola
361 così asincrona rispetto al refresh grafico. Tale task potrebbe essere creato
362 dal metodo OM_NEW della classe e distrutto in seguito da OM_DISPOSE.
363 Eventuali valori di ritorno diretti all'applicativo potrebbero essere
364 comunicati mediante messaggi (gestiti automaticamente dal task del gadget).
365
366 Il refresh grafico dei gadget, invece, essendo generalmente un'operazione
367 abbastanza rapida, potrebbe essere affidato ad un unico task globale; una
368 possibilità sarebbe quella di creare questo task all'apertura della libreria
369 MUIMaster.
370
371                                ::::::::::::::::::::::::   :::::::::::::::::::
372                                ::Operazioni programma::<==::Task del gadget::
373                                ::::::::::::::::::::::::   :::::::::::::::::::
374                  _ _ _ _ _ _ _ _ __                               /|\
375  _ _ _ _ _ _    |                  |    _ _ _   _ _ __     _ _ _ _ | _ _ _ _
376 |           |   |Semplice messaggio|   | \ \ \ \ \ \ \|   | \ \ \ \ \ \ \ \ |
377 |Intuition()|==>| all'applicativo  |-+ |Gestione input|==>|Esecuzione metodo|
378 |_ _ _ _ _ _|   | (IDCMP_MOUSE#?)  | | |_\_\_\_\_\_\_\|   |_\_\_\_\_\_\_\_\_|
379                 |__ _ _ _ _ _ _ _ _| |        /\                   |
380                                      |    _ _ ||_ _ _             \|/
381                                      |   | \ \ \ \ \ |  ;;;;;;;;;;;;;;;;;;;;;
382                                      +-->|Applicativo|  ;;Refresh della GUI;;
383                                          |_\_\_\_\_\_|  ;;;;;;;;;;;;;;;;;;;;;
384
385 Se le operazioni di refresh non necessitano di restituire alcun valore al
386 dispatcher dell'oggetto (oppure alla funzione di MUI che gestisce l'input)
387 quest'ultimo verrebbe disimpegnato immediatamente; in caso contrario sarebbe
388 sufficiente che il task preposto al refresh svolgesse tutte le sue operazioni
389 prima di rispondere al dispatcher con ReplyMsg(), e copiasse il valore di
390 ritorno in un apposito campo del messaggio "restituito" al mittente.
391
392 Questo ovviamente terrebbe impegnato il task dell'applicativo per un tempo
393 leggermente superiore, ma le operazioni di refresh grafico puro e semplice
394 non dovrebbero, nella maggior parte dei casi, richiedere più di qualche
395 millisecondo (come del resto accade per Intuition nel caso di gadget non
396 troppo complicati). Chiaramente se tale comportamento fosse richiesto per
397 TUTTI i gadget sarebbe più conveniente evitare del tutto l'uso di un task
398 separato per il refresh, mantenendo però quello dedicato al callback.
399
400 Sarebbero possibili diverse variazioni sul tema: ad esempio, l'ordine in cui
401 vengono "richiamati" i due task potrebbe influenzare, sia pure di poco, la
402 prontezza del refresh e quindi della risposta all'utente da parte della GUI;
403 oppure in certi casi potrebbe essere conveniente creare "al volo" il task
404 preposto al callback in modo che l'applicativo possa eseguire più volte
405 contemporaneamente la stessa funzione (se la sua natura lo consente).
406
407 In ogni caso questa soluzione eliminerebbe alla radice il problema del
408 "blocco" apparente della risposta della GUI durante un'intensa attività
409 dell'applicativo, senza per questo tornare al modello "mono-threaded"
410 adottato attualmente da Intuition. L'alternativa proposta per quest'ultimo
411 (vedi paragrafo precedente) risolverebbe in teoria anche il problema di MUI,
412 ma solo se i gadget MUI fossero istanze di "gadgetclass", cosa che al
413 momento, in pratica, non accade.
414
415
416 CONSIDERAZIONI FINALI
417
418 Funzionamento seriale dell'input.device
419 ---------------------------------------
420
421 Come già detto, l'input.device propaga lo stream di eventi di input
422 attraverso i vari handler in cascata. Gli handler non sono altro che
423 funzioni chiamate, una dopo l'altra, dal task dell'input.device; ogni
424 handler riceve in ingresso il valore di uscita del precedente (e cioè
425 il puntatore ad una particolare lista di InputEvent).
426
427 Questo è un meccanismo intrinsecamente seriale; inoltre esso implica che gli
428 handler di priorità più alta (come quello di Intuition) debbano esaminare,
429 tra gli altri, molti eventi che non li riguardano direttamente e che vanno
430 semplicemente trasmessi agli handler successivi.
431
432 Come aumentare il parallelismo nelle operazioni dell'input.device?
433
434 Ingenuamente si potrebbe pensare di avere diverse code, ognuna gestita da
435 un task indipendente, tra cui suddividere gli eventi in base al tipo degli
436 handler che tali code alimentano; ovviamente occorrerebbe che gli handler
437 di una coda non abbiano mai la necessità di trasmettere eventi a quelli di
438 un'altra coda.
439
440 Purtroppo in pratica questo non è una soluzione, dato che porterebbe a
441 ricreare la situazione corrente. Infatti normalmente gli handler esistenti
442 nel sistema sono pochi (per lo più Commodities, Intuition e console.device)
443 ed è difficile individuare tipi di eventi che non interessino, anche solo
444 potenzialmente, almeno due di essi.
445
446 In particolare, la quasi totalità degli eventi di input generati dall'utente
447 interessa in qualche modo Intuition, che viene ad essere un vero e proprio
448 "collo di bottiglia".
449
450 Più vantaggioso risulterebbe applicare questa soluzione al livello dei
451 singoli handler; ciascuno di essi, a meno che il suo funzionamento sia
452 molto semplice, potrebbe gestire l'input in arrivo ripartendolo in modo
453 opportuno tra diversi task paralleli (come illustrato riguardo al problema
454 di Intuition).
455
456 In questo modo sorgerebbe però il problema della trasmissione del flusso
457 di input lungo la catena di handler. Ognuno di essi potrebbe trasmettere
458 al successivo solo gli eventi che può scartare immediatamente come "non
459 rilevanti" per le sue attività, ma gli sarebbe preclusa la possibilità di
460 modificare gli eventi utilizzati, o crearne di nuovi in base ai risultati
461 della loro elaborazione, e reinserirli nella posizione originale: questa
462 operazione generalmente richiederebbe la conoscenza di dati non disponibili
463 a priori e, d'altra parte, una sincronizzazione con i suoi task per ottenere
464 da essi tali dati annullerebbe ovviamente tutti i vantaggi del parallelismo.
465
466 E` dunque necessario, volendo impiegare un simile modello:
467
468 · Stabilire delle regole estremamente precise per decidere quando l'ordine
469   relativo di due eventi vada mantenuto oppure sia ininfluente;
470
471 · Limitare al massimo la necessità di trasmettere informazioni tra un
472   handler e il successivo (nel caso di entità strettamente connesse, come
473   Intuition e console.device, questo potrebbe rivelarsi un problema serio);
474
475 · Assicurarsi, ad esempio mediante semafori, che venga sempre mantenuta la
476   consistenza interna dei valori che definiscono lo stato di un handler (e
477   quindi dell'entità software che si appoggia ad esso) anche in presenza
478   di numerosi sotto-task che possono accedere a tali valori.
479
480 Ad esempio, se l'utente attiva una finestra di Shell e poi preme un tasto
481 sulla tastiera, è necessario che il console.device riceva l'evento "finestra
482 attiva" PRIMA di quello "tasto premuto", nonostante il fatto che il secondo
483 potrebbe venire trasmesso immediatamente mentre il primo richiederebbe una
484 più lunga elaborazione da parte di Intuition.
485
486 Ancora, quando l'utente trascina un gadget proporzionale sarebbe auspicabile
487 che la posizione relativa di knob e puntatore del mouse rimanesse costante,
488 anche se gli spostamenti dei due oggetti vengono gestiti da due diversi task.
489
490 La trasmissione di eventi agli handler successivi potrebbe ad esempio essere
491 implementata mediante una coda ausiliaria globale svuotata periodicamente,
492 accessibile a tutti i sotto-task di un handler, purché si presti la massima
493 attenzione a mantenerla sempre perfettamente ordinata e ad inserire in essa
494 anche quegli eventi (e solo quelli) che, pur non dovendo essere elaborati
495 dall'handler corrente, possono risentire dell'ordine in cui vengono trasmessi
496 rispetto a certi altri eventi.
497
498 Queste considerazioni non pretendono certamente di costituire una soluzione
499 completa, preferibile ad altre o facilmente realizzabile; si tratta solo di
500 riflessioni su alcuni aspetti del problema di cui probabilmente converrebbe
501 tenere conto.
502
503
504 Fattibilità di un patch per Intuition
505 -------------------------------------
506
507 E` possibile, tramite un patch, applicare all'attuale versione di Intuition
508 i criteri appena esposti?
509
510 Probabilmente no.
511
512 L'idea sarebbe di applicare un patch alla funzione Intuition() per forzare
513 il passaggio dell'input ad un task separato che se ne occupi, permettendo
514 all'handler di Intuition di terminare subito la sua esecuzione. Ma anche
515 immaginando di risolvere quasi tutti i problemi prima descritti, resta sempre
516 l'impossibilità di garantire la consistenza dei dati PRIVATI contenuti nella
517 struttura IntuitionBase, a cui sarebbe facile, in questo modo, effettuare
518 un accesso asincrono.
519
520 Non è escluso che si possa trovare una soluzione anche a questo problema, ma
521 con ogni probabilità a questo punto conviene aspettare che sia Amiga Inc. ad
522 implementare nel sistema operativo una gestione dell'input più efficiente.
523