L'architettura basata sugli eventi significa semplicemente che il ciclo di eventi AKA del ciclo principale non comprende molto dei dati elaborati da un programma. Capisce solo abbastanza, che può inviare gli eventi giusti per i dati.
Quindi, ad esempio, se l'evento viene attivato da dati provenienti da un socket, tutto ciò che il ciclo di eventi deve sapere è, quale callback da chiamare, quando i dati provengono da quel particolare socket.
Tipicamente il ciclo degli eventi si trova in alcune librerie, come libevent . Quindi il codice dell'applicazione consiste solo del codice di installazione e dei gestori di eventi che vengono chiamati dal ciclo degli eventi nella libreria.
Dato che menzioni i thread: una semplice applicazione guidata da un evento classico è a thread singolo. Ogni gestore di eventi o callback esegue la sua azione il più velocemente possibile, quando viene chiamato e restituisce. Bloccare o aspettare o dormire è un grande no no , bloccherà tutti gli altri eventi!
I thread sono spesso usati, quando c'è qualche elaborazione che richiede molto tempo. Se fosse stato fatto nel thread principale con il loop degli eventi, la lunga operazione avrebbe dovuto essere tagliata in piccoli pezzi, così anche altri eventi potrebbero essere gestiti. Quindi è più semplice avere un thread di lavoro , che può eseguire l'elaborazione senza interferire con l'elaborazione degli eventi, e quindi generare un evento per il loop degli eventi principale una volta terminato.
Altro caso di usare thread è, quando c'è qualcosa che deve bloccare. Ad esempio potrebbe essere un'altra libreria, che fornisce solo una API di blocco . Se quell'API dovesse essere utilizzata dal ciclo di eventi thread principale, bloccherebbe altri eventi. La soluzione è usare quella libreria da un altro thread, che può bloccare e quindi generare un evento per il loop degli eventi principale quando c'è qualcosa di interessante per altre parti dell'applicazione.
Ma in un certo senso, l'architettura basata su eventi è una sorta di opposto dell'architettura multi-thread:
- Nella semplice architettura multi-threading, ogni thread attende un tipo di cosa da elaborare (una condizione di attesa o una coda di blocco o una lettura di socket bloccante o qualsiasi altra cosa, possibilmente con timeout per controllare periodicamente qualcosa), quindi l'elaborazione, probabilmente segnala altri thread e torna ad aspettare. Un thread fa una cosa, e c'è un thread per ogni diverso tipo di cosa da fare.
- Nell'architettura basata su eventi c'è solo un ciclo di eventi principale (di solito da una libreria) che attende tutti i tipi di eventi e gestori di chiamate, tutti nello stesso thread. Un thread fa tutto, e c'è un gestore di eventi non bloccante per ogni cosa diversa da fare. La cosa buona è che non è necessaria alcuna sincronizzazione, perché è tutto in un thread, che evita i bug multi-threading troppo comuni, mantiene il codice più semplice ed evita il sovraccarico della sincronizzazione. Il rovescio della medaglia non sta sfruttando i core CPU multipli, e il rischio di bloccare il ciclo degli eventi se lo sviluppatore è incurante.
Ovviamente un'applicazione complessa può avere diversi loop di eventi in thread diversi e anche thread che fanno una sola cosa, quindi possono essere mescolati.