Reactor pattern

Il Reactor Pattern è un Design Pattern per la programmazione orientata agli eventi e rientra nella categoria dei pattern concorrenti. Si applica ad un modello Client-Server in cui le richieste da parte dei client possono arrivare in qualsiasi momento in maniera concorrente. Viene anche chiamato dispatcher di eventi o notificatore.

Applicazione

Questo pattern trova applicazione in quei sistemi in cui il server deve gestire le richieste dei client in maniera concorrente senza:

  • bloccarsi indefinitivamente gestendo una singola richiesta,
  • troppe difficoltà per aggiungere nuove funzionalità.

Struttura

La soluzione prevede un Dispatcher che invia le richieste dei client al corrispondente gestore, disaccoppiando le componenti software di carattere generale da quelle specifiche dell'applicazione.

Componenti

  • Risorsa: un oggetto che rappresenta una risorsa del sistema operativo utilizzato dai client, su cui le operazioni possono essere bloccanti.
  • Demultiplexer sincrono di eventi: resta in attesa di eventi su un set di handle. In C/C++ nei sistemi UNIX questo può essere implementato con la chiamata di sistema select().
  • Inizializzatore del dispatcher: definisce i metodi per registrare, rimuovere e richiamare gli oggetti che gestiscono gli eventi (event handler).
  • Event handler: è un'interfaccia generica che espone il metodo gestisci_evento(). Le classi derivate implementano questo metodo secondo la loro necessità (fanno l'override del metodo)

Dinamica

  • L'applicazione registra un gestore di eventi (event handler) concreto sull'inizializzatore del dispatcher e gli fornisce un riferimento alla risorsa corrispondente.
  • L'inizializzatore crea un'associazione tra la risorsa su cui avverrà un evento e l'event handler in grado di gestirlo.
  • quando un evento viene rilevato su una risorsa, il demultiplexer sincrono chiama la funzione gestisci_evento() dell'event handler corrispondente.

Proprietà

I benefici apportati da questo pattern di programmazione sono un demultiplexing indipendente dall'applicazione e quindi riutilizzabile, oltre a modularità, estensione di funzionalità configurabilità molto elevate.

Si riscontrano però anche alcuni svantaggi:

  • applicabilità ristretta: gli eventi devono essere riferiti a oggetti del sistema operativo e quest'ultimo deve fornire una chiamata di sistema corrispondente alla select() in Unix.
  • non c'è prelazione: se un gestore di eventi chiama una funzione bloccante tutto il sistema si blocca. Le funzioni gestori di eventi devono quindi ritornare in tempi molto brevi per massimizzare la concorrenza
  • il debug è complicato in quanto il controllo oscilla tra demultiplexer e event handler.

Bibliografia

  • Yves Roudier, "Distributed Systems and Middleware", Institut Eurécom 2015

Voci correlate

  • Acceptor-Connector Pattern
  • Design pattern
  • Active-Object