ASRI : A Simple Reactor Implementation

asri/classasri_1_1EventHandler__inherit__graph.png

ASRI est un composant logiciel C++, utilisé par ActiCM qui simplifie l'écriture d'applications traitant des évènements (expiration de délais, messages reçus par une liaison TCP/IP, ....). Il est implémenté à l'aide d'une pompe à évènements.

ASRI est livré avec ses Tests Unitaires, une documentation extraite des sources par Doxygen, et des exemples.

Le concept n'a rien de nouveau. Malheureusement l'implémentation est souvent délicate, car l'écriture d'un Handler suppose une bonne connaissance des mécanismes du système d'exploitation. Ce code est difficile à tester et la moindre erreur coûte très cher en temps de mise au point. C'est le domaine favori des pannes pseudo aléatoires.

ASRI est une implémentation du pattern Reactor décrit par Douglas Schmidt, et utilisé pour l'implémentation d'ACE. Pour une descrition détaillée, voir reactor-rules.pdf

L'implémentation d'ASRI diffère beaucoup de celle du Reactor d'ACE, notamment sur les points suivants :

  • basée sur des bibliothèques C++ portables standard : STL, Boost et Log4cplus
  • exige un compilateur C++ capable de compiler les bibliothèques ci-dessus
  • les remontées d'erreur sont gérées par Exceptions
  • pas de gestion de configuration multi-OS par macros. L'implémentation courante ne fonctionne que sous Windows 2000 ou supérieur. Il serait certainement possible d'en tirer une version fonctionnant sous Linux.

Vous pouvez télécharger ASRI Documentation Reference, 500 Kb, format Chm (Win32 Compiled Html Help manual).

Concepts

  • Reactor implémente la pompe à évènements
  • EventHandler implémente le code générique de gestion des évènements
  • des Handlers abstraits dérivés de EventHandler implémentent le traitement d'un type d'événement particulier (expiration de délais, messages reçus par une liaison TCP/IP, etc). Ils peuvent être adaptés simplement à des besoins spécifiques

Les Handlers concrets dérivés des Handlers abstraits :

  • permettent de tester le Reactor, le EventHandler et les Handlers abstraits
  • servent d'exemple
  • sont utilisées dans les applications
  • sont ajoutés (ou enlevés) dynamiquement, par registerHandler() et unregister()

ASRI class diagram

asri/AsriReactor.png

Threads

  • Une application peut disposer de N Reactors différents, à condition de consacrer un Thread à chacun d'entre eux.
  • une fois que le réacteur est actif (un thread exécute la boucle d'attente), un mutex récursif permet de lever une exception si un autre thread appelle une des méthodes runEventLoop(), registerHandler(), stopEventLoop() and unregister() de ce réacteur.

Exemples

AsriClock.cpp : An application that registers 3 different Timeout Handlers and run the Reactor:

  • ExampleTimeBeeper, Log current time and beep every second, forever
  • ExampleCountDown, Log countdown value every 100 ms, unregister self when it is 0
  • ExampleLoopStopper, stopEventLoop and close application after 5 seconds

AsriEchoServer.cpp : A TCP Message server that echoes received messages.

This TCP server will :

  • listen on port 28000
  • stop listening (unregister self) when the 3th connection is closed by client
  • echo back each message received with "++" inserted in front of the data

AsriBasicConnector.cpp : A TCP Message client that sends a message, ignore the response and reconnects forever.

This TCP client will :

  • try to connect to a server on localhost listening on port 28000
  • if connection is refused : unregister self
  • send a message
  • if receiving a message : close the connection then try to reconnect
  • if connection is closed by server : try to reconnect