Énoncé (fichier pdf) - LabUnix

Transcription

Énoncé (fichier pdf) - LabUnix
Devoir #2 — INF5171 (gr. 20)
Automne 2016
Date de remise: Mardi, 22 novembre, 13h30. Un travail remis après l’heure indiquée
sera en retard ⇒ pénalité de 10 % par jour, partiel ou complet.
Aucun travail ne sera accepté après Jeudi, 24 novembre, 16h00.
Mise en oeuvre d’un espace de tuples de style
«Linda»
Les espaces de tuples
La notion «d’espace de tuples» a été introduite par Carriero & Gelernter dans le cadre d’un
langage appelé Linda.1
Linda est un «langage de coordination» qui peut s’intégrer à divers langages de programmation — des variantes existent pour C, Java, Ruby, ainsi que de nombreux autres
langages.
Linda combine des éléments de programmation parallèle par variables partagées et par
échange de messages : un espace de tuples est partagé entre des processus — chacun avec
son contexte privé — qui utilisent cet espace pour échanger de l’information, de façon
concurrente et atomique.
Dans ce qui suit, nous allons présenter une version Ruby des notions de tuples et d’espace
de tuples à la Linda, version que vous devrez mettre en oeuvre.
• Un tuple est une séquence finie d’éléments, de types variés, dont le premier élément
est nécessairement un Symbol — élément qu’on appelle la clé du tuple.
Un tuple est simplement un Array dont le premier élément est un Symbol — donc
un Array tel que size >= 1.
Voici quelques exemples :
# Un tuple ( de taille 1) avec une clé : foo
[: foo ]
# Un tuple ( de taille 2) avec une clé : foo et un champ : bar
[: foo , : bar ]
# Un tuple ( de taille 3) avec une clé : bar et des champs " abc " et 10
[: bar , " abc " , 10]
1
N. Carriero and D. Gelernter. «Linda in context.» CACM, 32(4):444–458, April 1989.
1
INF5171 (gr. 20) Devoir #2 (Automne 2016)
2
• Un espace de tuples — classe TupleSpace — est une collection de tuples. Un tuple peut apparaître plusieurs fois ; un espace de tuples est donc un multi-ensemble2
de tuples.
• Étant donné un TupleSpace ts, les trois méthodes de base associées à ts sont les
suivantes :
– ts.put le_tuple
Ajoute dans ts le_tuple indiqué.
– ts.take patron
Retire de ts un (1) tuple qui matche le patron — voir plus bas pour la notion
de patron de tuples — et retourne le tuple retiré.
Si aucun tuple qui matche le patron n’est présent, la méthode bloque jusqu’à
ce qu’un tuple approprié soit disponible.
Si plusieurs tuples matchent le patron, un (et un seul) tuple est retiré et retourné, tuple choisi de façon arbitraire (au choix de l’implémentation).
– ts.read patron
Retourne un tuple de ts qui matche le patron indiqué, mais sans retirer le
tuple.
Cette méthode bloque et fait un choix arbitraire si plusieurs tuples matchent de
la même façon que take.
Ces trois méthodes sont toujours exécutées de façon atomique et indivisible, même
en présence de threads multiples utilisant et manipulant l’espace de tuples.
Soulignons que d’autres méthodes sont disponibles, que vous devrez aussi mettre en
oeuvre, mais elles ne sont pas décrites dans le présent document : voir plutôt le fichier
lib/tuplespace/tuplespace.rb, la documentation yard,3 ainsi que les fichiers de
test.
2
3
En anglais, on dit aussi multiset ou bag.
http://www.labunix.uqam.ca/~tremblay/INF5171/Devoirs/TupleSpaceDoc/
INF5171 (gr. 20) Devoir #2 (Automne 2016)
3
• Un patron de tuples, utilisé dans les méthodes take et read,4 permet de décrire un
ensemble de tuples «potentiels».
Les principaux patrons sont les suivants :
– Patrons utilisés directement comme argument, donc au plus haut niveau, par
exemple, «ts.take nil» ou «ts.take :foo» :
Matche n’importe quel tuple
Matche n’importe quel tuple (donc de taille arbitraire)
dont la clé est :foo
/pat/ Matche n’importe quel tuple (de taille arbitraire) dont
la clé matche l’expression régulière /pat/
nil
:foo
– Patrons utilisés dans un champ d’un tuple, par ex., «ts.take [:foo, nil]»,
«ts.take [/(foo|bar)$/, "abc"]», «ts.take [:foo, Fixnum, /abc/]», etc. :
Matche n’importe quel objet
Ne peut pas être utilisé à la 1ère position (clé)
/pat/
Matche n’importe quel objet qui matche l’expression
régulière /pat/
NomDeClasse Matche n’importe quel objet de la classe NomDeClasse
(kind_of?(NomDeClasse))
n1..n2
Matche un entier qui fait partie du Range indiqué
valeur
Matche la valeur spécifique indiquée (égalité avec «==»)
nil
Pour plus de détails sur les patrons, voir les fichiers lib/tuplespace/tuple_pattern.
rb et spec/tuple_pattern_spec.rb.
4
Ainsi que dans les méthodes watch, unwatch et each : voir lib/tuplespace/tuplespace.rb.
INF5171 (gr. 20) Devoir #2 (Automne 2016)
4
Un exemple de programme «Hello World! »
Le Programme Ruby 1 présente le contenu du fichier bin/hello.rb, un programme de
style «Hello World! » utilisant un espace de tuples.
Voici un exemple d’exécution de ce programme :
$
=
bin / hello . rb 5
Hello du thread 2
Hello du thread 4
Hello du thread 1
Hello du thread 3
Hello du thread 0
FIN DU PROGRAMME
Ce programme illustre diverses utilisations des tuples d’un espace de tuples :
• :num_thread : Pour représenter une variable que l’on doit incrémenter de façon
atomique — on retire le tuple pour obtenir sa valeur courante, puis on écrit un
nouveau tuple avec la valeur modifiée.
• :verrou: Pour représenter un verrou d’exclusion mutuelle — ici, pour assurer que
les instructions puts, qui ne sont pas atomiques, s’exécutent sans interférence.
• :termine : Pour envoyer un signal de synchronisation de chacun des travailleurs vers
le coordonnateur de façon à indiquer la terminaison.5
5
Dans cet exemple, pour assurer la terminaison propre et correcte, on aurait aussi pu conserver les
descripteurs de thread, puis faire des appels à join sur ces descripteurs.
INF5171 (gr. 20) Devoir #2 (Automne 2016)
5
Programme Ruby 1 Un programme «Hello World! » avec un espace de tuples.
# !/ usr / bin / env ruby
require_relative ’ ../ lib / tuplespace ’
Thread . abort_on_exception = true # E n c a s d ’ e r r e u r d a n s l e s t h r e a d s !
## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Methode executee par chacun des threads .
## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
def travailleur ( ts )
# On o b t i e n t le p r o c h a i n numero d ’ i d e n t i f i c a t i o n .
_ , mon_num = ts . take [: num_thread , Fixnum ]
ts . put [: num_thread , mon_num + 1]
# On fait le " t ra v a i l "... de facon a t o m i q u e
sleep rand
ts . take [: verrou ]
puts " - Hello du thread #{ mon_num } "
ts . put [: verrou ]
# On i n d i q u e qu ’ on a t e r m i n e .
ts . put [: termine ]
end
## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Programme principal .
## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
nb_threads = ARGV . empty ? ? 10 : ARGV . shift . to_i
# On lance les threads , en s p e c i f i a n t l ’ espace de tuples a u t i l i s e r .
ts = TupleSpace . create
ts . put [: num_thread , 0]
nb_threads . times do
Thread . new { travailleur ( ts ) }
end
ts . put [: verrou ]
# On attend que tous les t h r e a d s aient t e rm i n e .
nb_threads . times do
ts . take : termine
end
puts " = FIN DU PROGRAMME "
INF5171 (gr. 20) Devoir #2 (Automne 2016)
6
Ce que vous devez faire
Divers fichiers vous sont fournis, sous forme d’un dépôt git :
$ git clone http://www.labunix.uqam.ca/~tremblay/git/TupleSpace.git
1. Vous devez compléter les méthodes de la classe TupleSpace de façon à satisfaire les
tests unitaires qui vous sont fournis.
2. Vous devez compléter le programme lib/wc.rb, qui utilise un espace de tuples pour
réaliser la même tache que l’exemple présenté dans les notes de cours — Sections 5.5.1
et 5.5.3.
La documentation des méthodes de la classe TupleSpace, en format yard, est disponible
à l’adresse suivante :
http://www.labunix.uqam.ca/~tremblay/INF5171/Devoirs/TupleSpaceDoc/
Votre mise en oeuvre de TupleSpace ne doit utiliser que les classes et méthodes de
base de Ruby, donc les classes Thread, Mutex, ConditionVariable, etc. — c’est-à-dire
les éléments présentés dans le chapitre 6 des notes de cours. Vous ne devez donc pas
utiliser les méthodes de la bibliothèque pruby!
Quelle machine vous devez utiliser
Les tests pour la correction seront exécutés sur la machine japet.labunix.uqam.ca,
avec jruby, qui fournit des «vrais» threads parallèles.
Par contre, comme vous n’utiliserez que les classes de base, vous devriez pouvoir
développer votre code avec n’importe quel Ruby. Or, il faut savoir que le lancement d’un
programme (de tests ou autre) avec jruby est nettement plus long que le lancement du
même programme avec ruby/MRI. Voici donc une suggestion quant à la façon de procéder
pour développer et tester vos méthodes, sachant que c’est ruby/MRI qui est installé sur
malt.labunix.uqam.ca alors que c’est jruby qui est installé sur japet.labunix.uqam.ca :
1. Commencez par tester votre(vos) méthode(s) sur malt, avec ruby/MRI — les tests
s’exécutent rapidement, donc vous pourrez les exécuter souvent et obtenir rapidement
du feedback.
2. Lorsqu’un groupe tests s’exécute avec succès sur malt, exécutez alors le même groupe
de tests sur japet avec jruby — donc avec des «vrais» threads parallèles.
INF5171 (gr. 20) Devoir #2 (Automne 2016)
7
Ce qui vous est fourni
Plusieurs fichiers vous sont fournis que vous n’avez pas à modifier — sauf, évidemment,
le fichier lib/tuplespace/tuplespace.rb :
1. lib/debug.rb : Méthodes pour aider au débogage, notamment une méthode jiggle.
2. lib/dbc.rb : Méthodes pour l’approche Design By Contract (DBC), donc pour
exprimer des pré-conditions, post-conditions, invariants et assertions.
3. lib/tuplespace/tuple_pattern.rb : La classe TuplePattern et ses diverses méthodes, dont la plus importante, la méthode «=˜».
4. spec/*_spec.rb : Diverses suites de tests unitaires définies à l’aide de MiniUnit —
voir plus bas pour les cibles de test, telles qu’identifiées par «rake -T».
5. Quelques exemples programmes qui utilisent un espace de tuples :
• bin/hello.rb
• bin/premiers.rb
• lib/wc.rb (à compléter!)
6. Rakefile, où les principales cibles sont les suivantes (sortie produite par «rake -T») :
rake
rake
rake
rake
rake
rake
rake
rake
test
concurrent
create_et_put
push_et_each
take_avec_match
take_et_read
tuple_pattern
watch
#
#
#
#
#
#
#
#
Run tests
Tests concurrents des methodes put et take
Tests (sequentiels) de create et put
Tests (concurrents) de push (<<) et each
Tests (sequentiels) de take avec patrons
Tests (sequentiels) de take et read
Tests du pattern matching des tuples
Tests de watch et unwatch
rake hello
rake premiers
rake wc
# Tests pour hello world
# Tests de la generation des nombres premiers
# Tests pour wc
rake remise
# Remise du travail avec oto
C’est la variable WIP (Work In Progress) qui indique la suite de tests à exécuter par
défaut — donc lorsqu’on exécute simplement la commande «rake». Initialement,
c’est la suite de tests create_et_put qui est active.
INF5171 (gr. 20) Devoir #2 (Automne 2016)
8
Ce que vous devez remettre
Remise papier
Vous devez remettre un document papier (dans la boîte du secrétariat du département)
contenant simplement le listage du votre fichier lib/tuplespace/tuplespace.rb — et
uniquement ce fichier!
Pour la remise de ce document papier, vous devez utiliser la page couverture (avec
grille de correction) disponible à la fin du présent du document.
Remise électronique
Vous devez remettre une version électronique du fichier lib/tuplespace/tuplespace.rb
en exécutant la commande suivante sur japet.labunix.uqam.ca :
$ rake remise
Note : Vous devez auparavant modifier la variable CODES_PERMANENTS dans le Rakefile
pour indiquer vos codes permanents (si vous travaillez en équipe, deux personnes maximum)
ou votre code permanent (si vous travaillez seul).
INF5171 (gr. 20) Devoir #2 (Automne 2016)
9
Remarques sur la correction
• Si le fichier remis contient des erreurs de syntaxe, alors vous perdrez une très (très!)
grande partie des points — voir plus bas.
• Une partie des points sera accordée pour la qualité et le style de votre code : présentation, clarté et simplicité, structure, choix des identificateurs, respect des conventions Ruby,6 etc. Par contre, même si la présence de commentaires est suggérée, je
n’évaluerai pas la présence, ou l’absence, de tels commentaires.
Deux principes de base pour la clarté du code : KISS et DRY.7
Autre principe pour la correction du style : plus je mets de rouge parce que je ne
comprends pas le code ou parce que le code est mal écrit, plus la note est faible
/
• J’effectuerai la vérification du bon fonctionnement avec d’autres tests que ceux qui
vous sont fournis — donc avec des tests privés additionnels.
En gros, la répartition des points sera la suivante : compilation correcte ≈ 20 %, bons
résultats sur les tests publics ≈ 60 %, bons résultats sur les tests privés ≈ 20 %.
Suggestions et indices
• La correction des travaux se fera sur la machine japet, avec jruby. Donc, vous
devez absolument vous assurer que votre programme fonctionne correctement sur
cette machine avant de le remettre.
• N’hésitez pas à introduire des méthodes auxiliaires — gardez votre code DRY, c’està-dire, éviter le plus possible le même code qui se répète.
• Utilisez git pour gérer l’évolution de votre travail et éviter sa régression, puisque le
code qui vous est fourni est déjà sous forme d’un dépôt local git. Donc, lorsque vous
avez réussi à faire fonctionner une partie de votre code, faites un commit!
Plus de détails sur git sont disponibles via la page suivante :
http://www.labunix.uqam.ca/~tremblay/INF5171/Liens/
6
7
https://github.com/styleguide/ruby
KISS = Keep It Simple, Stupid ; DRY = Don’t Repeat Yourself.
Travail remis à Guy Tremblay
INF5171-20 : Devoir 2
À remettre au plus tard Mardi, 22 novembre, 13h30
Ne pas mettre dans une enveloppe
Nom
Prénom
Code permanent
Courriel
Nom
Prénom
Code permanent
Courriel
Qualité du code
(KISS & DRY, respect des conventions Ruby)
create_et_put_spec.rb
take_et_read_spec.rb
take_avec_match_spec.rb
push_et_each_spec.rb
concurrent_spec.rb
{hello,premiers}_spec.rb
wc_spec.rb (et lib/wc.rb)
/ 10
Total
/5
/5
/5
/5
/5
/5
/5
/5
/ 45
Note globale
/ 10
Bonus : watch_spec.rb