Qu’est-ce que la réentrance ?
Les programmes sont habituellement constitués d’un ensemble de petites fonctions (bouts de code) qui exécutent des tâches précises, basées sur des algorithmes. Afin d’expliquer ce qu’est la réentrance, imaginons le scénario suivant :
Prenons une fonction d’un système d’exploitation quelconque qui permet d’obtenir l’heure courante. L’ordinateur emmagasine l’heure sous la forme d’une valeur, par exemple le nombre de secondes écoulées depuis 1904, et notre fonction convertit cette valeur en une chaîne de caractères (« 11 :59 ») et la retourne dans ce format au programme appelant.
Maintenant imaginons un programme qui fait appel à cette petite fonction CheckTime(). La fonction débute la construction de la chaîne de caractères selon la valeur du temps en ajoutant d’abord le premier « 1 », puis l’autre « 1 » et enfin les deux points « : »; c’est alors que le système d’exploitation interrompt la fonction (et par le fait même notre programme), car il est temps de donner la chance à un autre programme de s’exécuter.
Et voilà que ce second programme fait également appel à la fonction CheckTime(), il réentre dans la fonction. La fonction CheckTime() n’a aucun moyen de savoir qu’elle était à mi-chemin d’exécution pour notre premier programme, alors elle efface le contenu de la chaîne de caractères et recommence la conversion pour le second programme. Le second programme obtient la réponse « 11 :59 » et tout semble fonctionner correctement, jusqu’à ce que ce programme soit interrompu à son tour et que notre premier programme reprenne son exécution.
Le premier programme reprend à l’endroit où il était au moment de l’interruption, soit dans la fonction CheckTime(). La fonction avait débuté la construction de la chaîne de caractères et était rendu à « 11 : », il ne reste donc à la fonction que l’ajout des secondes « 59 ». Cependant la chaîne de caractères vaut maintenant « 11 :59 » car elle a été bâtie lors de l’appel par le second programme. Alors de quoi aura l’air le résultat de l’heure pour le premier programme ? « 11 :5959 », ce n’est pas exactement ce à quoi on s’attendait.
La récursivité est quelque peu reliée à la réentrance, les fonctions récursives sont des fonctions qui s’appellent elles-mêmes, alors elles ne sont pas seulement réentrantes, elles sont réentrées par elles-mêmes. La récursivité et la réentrance sont souvent enseignées au même moment et les gens les confondent quelquefois
Comment faire pour éviter ce genre de problème ?
Solution 1 – le blocage par les sémaphores.
La solution la plus évidente est le blocage, c'est-à-dire empêcher la réentrance. Par exemple, dès l’entrée dans la fonction CheckTime() je peux mettre en place une barrière virtuelle pour empêcher que d’autres programmes interrompent l’exécution dans la fonction jusqu’à ce qu’elle ait terminée son travail, la barrière virtuelle étant éliminée à la toute fin de la fonction. La fonction est dite atomique, c'est-à-dire qu’elle ne peut être interrompue ou stoppée, elle est un tout. Cette barrière virtuelle est fabriquée à l’aide de sémaphores. Cette solution n’est viable qu’à condition que le blocage soit de très courte durée, si le blocage dure trop longtemps, on empêcher les autres programmes de s’exécuter.
Solution 2 – les données relatives.
La meilleure solution est de bâtir la fonction afin qu’elle obtienne ses données à partir d’un pointeur (variable) qui lui est passé en paramètre par le programme appelant. Si mon programme utilise ce pointeur pour lire les données et que ce pointeur est différent pour chaque programme qui appelle la fonction, alors il est impossible que les données deviennent invalides ou corrompues.
Conclusion
En réalité il existe d’autres solutions que celles mentionnées plus haut, et très souvent il s’agit d’une combinaison de ces 2 solutions. Dans certaines situations il est préférable de réaliser un blocage de très courte durée.
La réentrance est un concept assez simple en théorie, mais bien des programmeurs l’ignorent. J’ai déjà obtenu un emploi parce que j’avais pu expliquer ce qu’était la réentrance et comment écrire des fonctions réentrantes.