
Envoyé par
Canopus
bufferisé, deadlock, queke ça signifie ?
Un buffer (aussi appelé tampon en français) est une zone mémoire où les entrées ou les sorties sont stockés temporairement, de façon à les accumuler de sorte que les "véritables" entrées/sorties soient moins nombreuses et plus volumineuses (car faire des entrées/sorties est très couteux indépendamment de leur taille, quel que soit l'OS (car on est obligé de faire un appel système et d'attendre le matériel)). Une sortie bufferisée (horrible anglicisme mais bon...) est une sortie qui va passer par un buffer, c'est le cas en Perl des sorties effectuées avec print().
En réalité il n'est pas possible de faire en sorte que print() ne soit plus bufferisé, mais on parvient à un résultat similaire en activant l'autoflush, qui en fait effectue automatiquement un flush() après chaque print() : flush() est une fonction (non accessible directement depuis Perl) qui va vider le buffer en effectuant une véritable sortie immédiatement.
Pour activer l'autoflush sur un handle de fichier il faut placer la variable spéciale $| à une valeur vraie (1 par exemple) lorsque le handle est actif. Par défaut à l'origine c'est STDOUT qui est actif, et pour changer de handle actif il faut utiliser select(). Par exemple pour activer l'autoflush sur FILE :
1 2
| select( FILE );
$| = 1; |
Mais ce bout de code a un problème : il ne réactive pas le handle de fichier précédemment sélectionné après avoir activé l'autoflush. Or la plupart des programmeurs assume que STDOUT est sélectionné par défaut et écrive :
print "Hello world ! \n";
En assumant que l'affichage se fera sur la sortie standard, mais en réalité si le HANDLE de sortie n'est pas explicite, print() écrit sur le handle actuellement actif, autrement dit FILE après notre bout de code précédent, et non pas STDOUT...
C'est pourquoi on utilise plutôt un code qui resélectionne le handle précedemment actif, aidé en cela par le fait que select() retourne ce handle :
1 2 3
| my $oldfh = select( FILE );
$| = 1;
select($oldfh); |
Ou de façon plus idiomatique :
select( ( select(FILE), $| = 1 )[0] );
En fait, on a :
( select(FILE), $| = 1 )[0]
qui active FILE, puis active l'autoflush sur FILE, les deux instructions sont entourées par des parenthèses, qui en font un pseudo-tableau, dont les valeurs sont (handle précédemment sélectionné, 1) = (valeur de retour de select(FILE), valeur de ($| = 1)), on prend la première de ces valeurs avec [0], et on la select()ionne, revenant ainsi à la situation préalable à cette ligne, mais avec l'autoflush activé sur FILE... (la valeur de ($| = 1) est 1 de façon à pouvoir écrire $x = $| = 1 et obtenir le résultat intuitif)
Un deadlock est une situation où deux processus/threads s'exécutant concurremment (autrement dit en même temps et parallèlement) attende chacun que l'autre le débloque avant de débloquer l'autre, ils ne se débloqueront donc jamais d'eux-même et c'est une cause fréquente de bugs dans les modèles classiques de concurrence.
--
Jedaï
Partager