le jeudi 11 janvier
2007
Bon, voila, c'est la nouvelle année. Il ne s'est pas passé grand chose de spécial, si ce n'est que la météo est particulièrement chaude... Sinon, j'ai pas grand chose à dire, vu le faible nombre de posts présents.
J'ai repris les travaux sur CyberRail : je réfléchit assez souvent sur comment architecturer le truc, mais c'est pas évident : je manque de recul pour faire quelques chose de performant.
J'ai fini par installer PyQt 4.1 (pour Qt 4.2) à la main: je sais pas ce qui coince chez Debian, mais ça fait 3 mois qu'il est sorti, et c'est toujours pas dans le dépot, ça en devient pénible.
La prochaine étape est de faire un éditeur de réseaux. Je pense qu'en partant de là, j'arriverais à poser mes idées, et surtout tester réellement ce que vallent mes idées. J'espère revenir ici avec quelques captures d'écrans.
le samedi 11 novembre
CyberRail, le retour
Bon, ça fait longtemps que je n'ai pas parlé de CyberRail. Le developpement s'est un peu arreté du fait d'autres projets, et aussi du fait que PyQt ne supportait pas encore Qt 4.2 et ses fameuses QGraphicsView (qui permettent de faire simplement des animations tout en optimisant les ressources). J'attend encore que cette nouvelle version de PyQt soit mise dans Testing, et je pourrais enfin l'utiliser !
Sinon, je réfléchi toujours à la façon dont je vais mettre en place les différents modules, et comment ils communiqueront les uns avec les autres. L'idée à laquelle je réfléchi depuis quelques temps est que l'interface graphique qui affichera les mouvements des trains sera considéré comme un réseau physique, comme le serait n'importe quel diorama. Il y aura donc un véritable réseau ferrovière avec ses propres contraintes (alimentation électrique, etc), tout ça émulé en logiciel. L'interet, c'est qu'ensuite, le reste du système n'aura pas à se soucier de savoir si le réseau derrière est une représentation informatique ou un vrai vrai réseau avec des vrais trains en plastique :-)
Sinon, je réfléchie toujours à la façon de mettre en place un système de signalisation simple à mettre (c'est à dire à l'aide d'interface graphiques) et qui resterait toujours aussi flexible pour pouvoir créer des familles de signaux hétérogènes (par exemple, pouvoir faire cohabiter la signalisation du métro parisien avec celle de la SNCF, ou pourquoi pas celle des tramway, qui fonctionne de façon completement différente). Je pense que je vais faire différents shéma pour expliquer les différents cas de figures auquel je pense.
le dimanche 16 avril
Le salon de la moquette et du modèle réduit
À l'origine, on devait aller voir l'expo Star Wars avec Guillaume, Adeline et Mickael. Finalement, on est allé Porte de Versailles voir le salon de la maquette et du modèle réduit. C'est la deuxième fois pour moi, et j'ai été déçu qu'il n'ai pas été couplé au salon du jeu de société. M'enfin bon. Cette année, cela a été veille technologique (on dit aussi piratage d'idées[1], ou plus simplement documentation sur ce qu'il se fait) en ce qui concerne les maquettes de trains électriques. Le but était de voir ce qu'il se fait plus exactement. Avant de commencer les détails à la con, je vais parler du reste.
J'ai aussi pu voir des maquettes de voitures et d'avion, ainsi que de bateaux (plus grand que le reste en moyenne). En ce qui concerne les voitures, il y en a eu au 5ème, au 10ème (ratio de reduction par rapport au modèle réel, le cas échéant). Une jolie demonstration de vitesse et de cascade, on a même eu droit à un super lourd à moteur thermique.
Il y a également eu des démonstrations d'avions et d'helicoptères de toutes tailles et de toutes velocités, à moteurs électriques ou thermiques. On a pas pu voir le rafale voler, mais rien que le bruit et l'odeur qui se dégageait du moteur à réaction[2] laissaient imaginer la puissance de la machine... On pouvait acheter, mais je ne l'ai pas fait parce que je n'avais ni les sous ni la place, des soucoupes volantes télécommandées. Mouahaha, ça viendra un jour ! Il y avait toute une partie du salon réservée à la robotique (barman automatique, machine à déssiner, joueur de babyfoot (très con, mais très rapide), et une démonstration d'aspirateur automatique (pas très futé non plus). Evidemment une partie consacrée aux dioramas & maquettes de réseaux férroviaires.

Ce qui m'interessait plus particulièrement étaient les réseaux pilotés par informatique, et je n'en ai trouvé qu'un vraiment interessant. La plupart des autres circuits font encore appel à de l'electronique de base (un potentiomètre couplé à quelques interrupteurs, ainsi que quelques boutons à contact secs pour les appareils de voie). Dans la plupart des cas, les signaux ne suivaient pas vraiment.
La maquette Märklin était, elle, pilotée par leur console automatisée. C'était pas mal, mais ça manquait de diversité. On pouvait y voir un système à deux anneaux avec cantons. Les deux anneaux étaient intépdendant l'un de l'autre, ce qui est dommage, je trouve. La signalisation des cantons suivait, c'est un point positif. J'ai pu entrapercevoir un autre logiciel de pilotage de réseau, mais le stand étant axés petits gamins appuyant sur les boutons, je n'ai pas chercher à allé voir plus loin (j'aurais du, je pense).
Il y avait donc au milieu de tout ça un mec qui a fait une très grande maquette (United Pacific Railroad ou quelques chose comme ça) pilotée par ordinnateur, et qui exploitait vraiment cette capacité (circulation dans les deux sens sur une seule voie, possibilité de manipulation d'une rotonde, d'un pont mécanique, etc), et la signalisation était correcte. Le monsieur a fait son programme avec WinDev (pour une fois que je vois une application sortie de ce truc), et ça marche tout à fait correctement. Finalement, ça semble ne pas être si mal (je n'ai jamais testé, cela dit). L'affichage est simple mais efficace d'un point de vue clarté. C'est un quadrillage de bitmaps qui est mis à jour en fonction de l'état du réseau. Je pensais, pour ma part, faire quelques chose de plus évolué avec Cyberrail, mais d'un autre coté, il faut voir si c'est vraiment pertinent s'il y a une vrai maquette derrière tout ça.
En ce qui concerne CyberRail, mes reflexions me confirment qu'il me faut un véritable simulateur de réseau logiciel si je veux arriver à faire qqch de crédible (qui pourrait par exemple être l'interface graphique toute jolie). Ce simulateur recevrait les mêmes évenements que n'importe quel autre matériel (signal à la valeur truc, aiguillage en position blabla, et qui renverraient les positions des trains suivant les pseudos capteurs posés sur la voie).
En ce qui concerne les capteurs, j'ai confirmation qu'il ya plusieurs méthodes. La plus classique reste la détection de changement de tension au passage de la loco. Chez Märklin, vu qu'ils ont un troisième rail (en fait, des plots au mileu de la voie), ils peuvent se permettrent des essieus métalliques, qui permmettent une détection de l'ensemble des wagons au lieu de juste la locomotive.
Il ya une autre famille de détecteurs, plus proche de la réalité, qu'on peut classer dans les pédales de voie. Il s'agit de détecteurs indépendants du système électrique qui détecte la présence d'une loco, d'un wagon, ou des roues sur l'interieur du rail. J'ai pris quelques photos, et j'ai passé la barre des 7000 photos sur mon disque :-) D'ailleurs, je commence un peu à manquer de place, je ne sais pas trop comment m'y prendre... Bon, les photos :

On peut apercevoir les piquots centraux qui forment le troisième rail, ainsi que la pédale qui signale le passage d'un train (par contact probablement)
Un jeu de trois pédales placées au centre de la voie, déclenchée par le passage de la loco, ou d'un wagon spécialement équipé.
le mercredi 5 avril
suite interface
Bon, suite à des problèmes insolubles d'angles et de courbes de bezier, les voies resteront droites. De toute façon, ça ne sera pas la vrai interface, mais juste un truc qui permet de controler visuellement ce qui se passe.
Je me suis peut-être embrouyé les pinceaux, mais la géométrie, ça devient compliqué à un certain point, surtout quand on commence à calculer des moyennes d'angles : bien que pi * 1.5 et pi * 3.5 soient exactement la même chose, la moyenne des deux donne l'opposé, ce qui est pénible quand tout est complètement dynamique (bah oui, le moteur ne se soucie pas de la gueule des coordonnées). Bon, faut ajouter à ça les formules trigonométriques qui ne retournent pas d'angles supérieurs à 2pi, donc, si on veux faire des angles plus grands, et bien il faut bidouiller. Bref, je me limiterais aux calculs de base.
Donc, si quelqu'un n'est pas content, il n'a qu'à programmer le truc.
Bon, j'ai aussi corriger un bug auquel je n'avais pas pensé :
Si deux modules identiques se connectent (et qu'ils n'ont pas activés le mode exclusif, auquel cas, le deuxième se fait jeter), il est fort probable qu'ils réagiront de la même façon. Ainsi, s'ils voient passer le message indiquant qu'un nouveau réseau est chargé, alors ils vont tous le réclamer. Le système fonctionne en diffusion, tout le monde reçoit tout ce qui passe (c'est un peu plus compliqué, mais bon), donc si les données du réseau transitent, tous les modules interessé les reçoivent. Cela signifie qu'une seule requete est nécessaire pour que tout le monde reçoivent les données attendues. Donc, si tous les modules identiquent génèrent chacun leur requete dans leur coin, le réseau précédement chargé transitera n fois, du nombre de modules ayant généré la requête, et chaque module affichera le même réseau n fois, ce qui n'est pas particulièrement génial.
Pour corriger le probleme, il y a maintenant un système d'élection pour désigner un module mandataire parmis les jeux de modules identiques. Seul celui-ci prend la parole lorsque les modules ont des requetes à faire qui pourraient générer des doublons.
le mardi 4 avril
CyberRail, un début d'interface graphique
Bon, et bien, ça faisait longtemps que je n'y avais pas touché, mais ce soir, je me suis mis à faire une petite interface graphique pour visualiser les réseaux. Rien de bien formidable, mais ça permet de voir si le réseau qu'on a pensé à bien la tête qu'on a espéré.
Pour le moment, c'est encore en construction : les courbes ne sont pas courbes, mais à terme, elles le seront. Le principe est de vois si les aiguillages s'emboitent bien correctement en fait.
Un autre truc que j'ai trouvé très sympa, c'est que le système que j'ai choisi étant completement MVC, on peut relancer l'interface graphique sans avoir à relancer le reste, et celle-ci se rafraichie automatiquement quand le réseau change, sans avoir à faire quoique ce soit. Moi, je trouve ça bien :-)

le mardi 24 janvier
Concurrence
- 1ère étape : aller sur http://www.bahnvf.de/
- 2ème étape : installer la chose sur un windows
- 3ème étape : lancer le programme, regarder l'exemple de la gare de triage
- 4ème étape : conceptualiser le fait que pour mettre ça en place dans CyberRail, ça va pas être facile
- 5ème étape : télécharger Paris Nord Est 2005
- 6ème étape : pleurer en constatant que la simulation gère même les taxis, en plus des heures de pointes et de la longueur des trains
- 7ème étape : bah ya encore du travail !
Bon, j'ai vraiment été impressionné par l'exemple de la gare de triage, avec les locos qui se (désa)couplaient pour reprendre les convois formés au fur et à mesure. Notamment, la technique de couplage/désacouplage est parfaitement maitrisée !
Pour arriver à un tel résultat, le moteur qui est derrière est assez compliqué à utiliser (je passerais sur l'ergonomie toujours aussi extravagante) : pour gérer un circuit, il faut indiquer aiguille par aiguille dans quelle position se mettre suivant l'itinéraire que doit suivre le train... Enfin bref, je me dis que pour que mon simulateur ressemble à quelque chose, et bien ce n'est pas gagné du tout du tout...
En fait, pour le moment, j'ai juste fait une petite brique, maintenant, il reste à faire le reste...
le vendredi 2 décembre
Protocole de Cyberrail
J'ai jamais vraiment abordé le fonctionnement que j'ai choisis pour ce projet. Le principe est simple : un module principale (le nom n'est peut-être pas très bien choisi) au centre du système attend la connexion de tous les autres modules et redistribue les messages reçus vers les modules concernés. Chaque module, à la connexion, précise les messages qu'il veut recevoir, et réagit en fonction des messages qu'il reçoit, en envoyant d'autres messages.
L'idée derrière tout ça est de bâtir un système programmé par évenement : le fonctionnement du programme ne serait qu'une suite d'évenements dont certains seraient la conséquences d'autres, et les autres produits par le matériel sous-jacent (le réseau en l'occurence). L'ensemble communique via des sockets ordinaires, permettant une distribution du système sur plusieurs machines si nécéssaire.
Pour me faciliter la tâche, notamment en ce qui concerne toutes les communications réseaux, je me suis fait une petite bibliothèque de socket qui fonctionne par évenement. Elle commence à devenir mature, puisque je ne la retouche quasiment plus et qu'elle réagit exactement comme je le souhaite (distribution des évenements, bloquante mais pas trop, gestion correcte des déconnexions, etc.). Par dessus cela, j'ai rajouté une couche de protocole pour mettre en forme un minimum la communication. L'échange d'information se fait sous forme de texte. Les données sont envoyées structurées grace à des dictionnaires en python qui sont écrit grace au module pretty print et lu grace à la fonction eval(). Je n'ai donc presqu'aucun travail d'analyse de flux à faire, et la sérialisation se fait toute seule.
Au final, l'écriture d'un module est rendu triviale. Il suffit d'instancier une classe CyberrailConnection, d'enregistrer les type de message qui nous interesse et auxquels sont associés des callback, et enfin d'appeler la fonction main() de cette classe. La négociation avec le module principal se fait tout seul et les évenements arrivent directement. Le module principale envoie toujours au début un message de bienvenue permettant au module de reprendre la main s'il a envie d'initier une communication.
Je pense avoir fait le gros du travail sur la couche de communication entre processus. Le fait de faire découpage clair permet une conception bien plus robuste du système, c'est un avantage non négligeable.
Réseau ferré et graphe
Je viens de m'apercevoir qu'un reseau ferré n'était pas vraiment un graphe, voir même pas du tout.
Prenons l'exemple simple d'un graphe connexe :
Comme on peut le voir, le noeud 3 est relié aux noeuds 1, 2 et 4. Si on suit la logique des graphes, les noeuds 1 et 2 sont reliés entre eux par le noeud 3, et un train, par exemple, pourrait passer par le noeud 3 pour aller du noeud 1 au noeud 2. Le probleme, c'est que ça ne marche pas à l'échelle d'une voie.
Prenons un exemple un peu plus proche de la réalité :
Dans cet exemple, les noeuds 1 et 2 sont effectivement reliés par le noeud 3, mais il serait impossible pour un train de passer sur l'autre voie du fait de l'orientation de l'aiguillage. En provenance de 1 ou de 2, les trains ne peuvent que aller vers 4 une fois passés 3.
Toutes ces explications pour montrer que les représentations classiques de graphes en mémoire ne fonctionnent pas pour des voies ferrées. En effet, si on reprend notre exemple, on peut poser les choses de la façon suivante :
{'links': {10: {'link': (1, 3)},
11: {'link': (2, 3)},
12: {'link': (3, 4)}},
'node': {1: {'pos': (1, 1)},
2: {'pos': (2, 1)},
3: {'pos': (2, 2)},
4: {'pos': (2, 3)}}}
Chaque noeud défini ses coordonnées, et chaque lien indique entre quel et quel noeud la liaison est faite. Le problème, c'est que de façon algorithmique, on ne sait absolument pas les chemins qui sont possibles de ceux qui ne le sont pas. Deux solutions à ce probleme :
- on indique à chaque noeud les traversées qui sont possibles de celles qui ne le sont pas. Cela fait beaucoup de traitements pour indiquer les combinaisons possibles. D'autant plus que si on commence à faire un aiguillage triple connectés à un autre aiguillage tripe, cela fait 3 × 3 = 9 liaisons différentes. Le problème n'est pas un probleme de mémoire mais de traitement. Sans compter que les liaisons sont courrues d'avances (faciles à déterminer). Un autre probleme, plus génant, est que ce sont les noeuds qui portent cette informations, et qu'ils deviennent donc dépendants des liens. Cela entraine une boucle dans la structure de donnée, et ça c'est mal (en plus, en python, c'est potentiellement relou).
- une autre solution, beaucoup plus élégante mais moins polyvalente, consiste à préciser à chaque bout de voie (dans le lien, donc) une étiquette précisant à quelle autre type de bout de voie il peut être connecté. Cette façon de faire est beaucoup plus complexe à comprendre, mais en terme d'implémentation, ça marche tout seul et c'est efficace.
Donc, pour chaque bout de pièce de rail, on associe une valeur parmis un ensemble de deux valeurs. J'ai pris l'ensemble booléen constitué de deux éléments (vrai et faux). Je ne sais pas si c'est tres pertinent vu que j'enlève complètement la sémantique de valeur de vérité dans ce cadre précis. Les bouts de pièces doivent être racordés de façon à ce qu'un bout de pièce "vrai" soit connecté à un bout de pièce "faux". Cela marche dans tous les cas puisque ces deux morceaux sont forcément en opposition (l'un en face de l'autre). Par contre, certaines pièces, comme des pièces en forme de U auront deux bouts avec la même valeur. Ce n'est pas génant du moment puisque les pièces qui y seront racordées seront à la valeur opposée.
De façon arbitraire, j'ai décidé que les valeurs "vrai" et "faux" seraient répartis de la façon suivante. C'est juste une convention qui marche à tous les coups, mais si à un moment elle n'est pas respectée, le système fonctionnera du moment que les "vrais" bouts sont connectés aux "faux" bouts.
J'aurais pu intercaler "vrai" et "faux". La seule contrainte est que l'opposé d'une branche corresponde à l'opposé d'une valeur.
Cela fonctionne en deux dimensions. Si un jour quelqu'un s'amuse à faire une représentation en 3D, ça marchera aussi. Je part du principe qu'il n'y aura pas d'aiguillage à la verticale (Disgression en passant, le système de gestion accepte n'importe quel type de coordonées (qui sont considérés comme des étiquettes). Libre à vous de mettre en coordonnée "Chez ma grand mère").
Pour notre exemple, cela donnerais :
{'links': {10: {'link': (1, 3), 'side': (False, True)},
11: {'link': (2, 3), 'side': (False, True)},
12: {'link': (3, 4), 'side': (False, True)}},
'node': {1: {'pos': (1, 1)},
2: {'pos': (2, 1)},
3: {'pos': (2, 2)},
4: {'pos': (2, 3)}}}
Notez que la déduction que les noeuds 1 et 2 ne sont pas accessibles l'un à l'autre peut maintenant se faire puisque la valeur de vérité de chacun des bout est "vrai". Par contre, la troisième liaison est possible puisque la valeur est "faux". En image, cela donne :

Pour ceux qui n'ont rien à faire, voici la structure de test sur laquelle je travaille. Elle est un peu différente, mais le principe est le même. Envoyez moi vos images :-)
{'junctions': {(1, 4): {'id': 80},
(4, 1): {'id': 10},
(4, 7): {'id': 70},
(5, 1): {'id': 20},
(5, 7): {'id': 60},
(6, 1): {'id': 30},
(6, 7): {'id': 50},
(9, 4): {'id': 40},
(9, 5): {'id': 90}},
'links': {5: {'link': ((1, 4), (4, 1)), 'side': (True, True)},
15: {'link': ((4, 1), (5, 1)), 'side': (False, True)},
25: {'link': ((5, 1), (6, 1)), 'side': (False, True)},
35: {'link': ((6, 1), (9, 4)), 'side': (False, True)},
45: {'link': ((9, 4), (6, 7)), 'side': (False, False)},
55: {'link': ((6, 7), (5, 7)), 'side': (True, False)},
65: {'link': ((5, 7), (4, 7)), 'side': (True, False)},
75: {'link': ((4, 7), (1, 4)), 'side': (True, False)},
85: {'link': ((9, 4), (9, 5)), 'side': (False, True)}}} le lundi 21 novembre
Modèle de voie
Bon, pour mon simulateur de réseau ferroviaire, j'ai mis au point le système de voie qui servira à afficher les voies ferrées à l'écran.
Pour afficher correctement une voie avec tous les appareils de voie, le ballast et les traverses (ou n'importe quoi d'autre), il ne suffit pas de coller comme un mal propre quelques images en croisant les doigts pour que ça tienne. Et pour pouvoir représenter une traversée jonction double, il faut un petit moment de reflexion pour que tout rentre bien.
Le principe est d'utiliser des images transparentes savamment intercalées afin de produire l'effet recherché. Derrière ce charabia à tendance juridique se cache une idée très simple : on dessine d'abord le ballast, puis les traverses, puis enfin les rails. Pourquoi pas tout d'un coup ? En fait, pour pouvoir correctement dessiner les appareils de voie (les aiguillages), il ne faut pas que le ballast et les traverses soient redessinées par dessus les rails deja dessinés. Le probleme se pose également entre le ballast et les traverses
Une fois le probleme des traverses reglé, il faut voir si le système permet de représenter les appareils de voie complexe, comme les traversées jonctions simples et double, ainsi que les croisements en tout genre. Je suis partit du principe que "qui peut le plus peut le moins" et que si j'arrive a modéliser une traversée, le reste suivrait sans probleme.
Déjà, présentons la bête en taille réelle :

Deux voies se croisent et l'appareil permet indiferrement d'aller sur l'une ou l'autre des voies de sortie à partir de l'une ou l'autre des deux voies d'entrée.
A partir de mon idée de quadrillage, je me suis dit qu'il pouvait être fait la même chose. Voila deja le schéma de conception :

Les pièces numérotées en noir sont les voies de passages. Les voies 14 et 16 sont des morceaux d'aiguillage simple. La voie 15 est un croisement à 45° de la voie 7. On s'aperçoit que les voies 17 et 18, qui forment la traversée (avec les voies 15 et 7) sont les mêmes que les 14 et 16. Si ça marche sur le schéma de principe, ça devrait fonctionner sur un schéma à l'échelle.
J'ai donc pris comme unité de quadrillage des images de 99 pixels sur 99. Cela permet d'avoir une diagonale mesurant l'équivalent de 140 pixels alignés (en considérant que les pixels sont carrés). Cela dit, en fait, une diagonale d'un carré de 99 pixels de coté comprend... 99 pixels ! C'est le genre de petites subtilités qui fait faire plein d'erreurs si on ne prend pas garde à la façon dont on raisonne... Cela donne, pour une vois simple :

Cela commence à se corcer lorsque l'on veut faire une vois en diagonale, parce qu'une bête rotation ne suffit pas. Et puis, il fallait que le cadre rose reste à la même position. De plus, il faut faire en sorte que les rails dépassent de ce cadre afin qu'ils soient reliés aux rails situés sur la diagonale. J'ai pensé très brievement à utiliser des hexagones, mais non, beaucoup trop complexe pour modéliser un réseau physique. J'ai donc dû calculer de combien de pixels les rails allaient déborder (Vive Pythagore). Au final, ça donne ça :

La troisième pièce, la plus dure à réaliser, est la courbe, nécessaire pour décrocher d'une voie verticale vers une voie en diagonale. Le plus chiant a été de bien faire coïncider les morceaux de rails avec des courbes harmonieuses et tengeantes à la droite de sortie.

Une fois les éléments de base fabriqués, il ne reste qu'à les imbriquer les uns dans les autres, en les faisant pivoter si besoin est. Le résultat est particulièrement réussi :

Une fois cette image obtenue, on peut enlever toutes les traces de conception, ce qui donne un résultat qui sera proche de la réalité :

le lundi 7 novembre
CyberRail
CyberRail, c'est le nom de mon future simulateur/contrôleur de réseau férroviaire.
Hier soir, en panne d'inspiration pour occuper ma soirée[1], je me suis mis à écrire la couche communication de ce projet. Il s'agissait de faire une couche réseau simple et qui fonctionne par évenement.
Actuellement, quand vous voulez faire de la communication réseau de manière asynchrone, on vous parle tout de suite de thread et autres concepts de ce genre. La parrallélisation des tâches, c'est bien gentil, mais ça apporte une certaine complexité qui finalement masque les intérêts de cette technique. L'autre moyen utilisé est l'appel système poll(). Sa programmation est assez complexe, et à la fin, en général, on s'emmele les pinceaux plus qu'autre chose.
J'ai décidé d'écrire CyerRail en python, parce que c'est ma marrote du moment, parce que c'est simple à écrire, parce que c'est moins lourd que Java et plus lisible que le C. La bibliothèque python fournit tous les appels systèmes de la libc, et notamment l'api BSD socket, ainsi que l'api select (qui contient l'appel système poll()). tout l'interet de le faire en python est que la gestion d'erreur est triviale : il n'y a pas de code de retour, les erreurs sont gerées par des exceptions, il n'y a pas de taille de buffer, etc, etc...
Cette simplification de l'api, ainsi que la notion d'objet, permet de se concentrer sur le fonctionnement réel du système, et donc de ne pas perdre de vue le but vers lequel on veut tendre. J'ai donc réussi hier soir à réalisé une petite bibliothèque multi-connexions ne fonctionnant qu'avec un seul thread (cela dit, le reste du programme devra peut-être tourner avec un autre thread en cas d'interface graphique ou autre...) quelque soit le nombre de connexion à gérer.
La bibliothèque communique avec le reste du programme par un système d'écouteurs : en cas de nouvelle connexion, des évenements sont envoyés à qui veut bien l'entendre et permettent un éventuel traitement par le reste du programme. J'ai également intégré deux niveaux d'évenements : ceux bas niveau (poll retourne, des octets sont envoyés ou reçu, une connexion s'est créée ou a été fermée), et ceux de haut niveau (liaison établie, une requète a été reçue, etc...).
Le seul problème est que la portabilité Windows n'est pas assurée. En effet, le problème est le suivant. Un appel externe à la bibliothèque demande l'envoie de données. Ces données sont ajoutées dans une file, et devraient être envoyées au porchain tour de boucle de poll. Malheureusement, poll n'a pas été avertit qu'il devait vérifier si des données peuvent être envoyées sur la socket. Résultat, poll ne peut pas prendre en compte les nouvelles données, et reste bloqué jusqu'à ce qu'un autre évenement vienne le réveiller. Comme cet évennement est completement indépendant des données à envoyer, on ne peut pas garantir que les données partiront, et encore moins qu'elles partiront tout de suite. L'astuce est donc de créer un tube (un pipe), et de mettre la sortie dans la liste des descripteurs que poll doit surveiller. Lorsque l'on veut envoyer des données, il suffira dont de mettre un caractère dans l'entrée du tube, ce qui aura pour effet de réveiller poll. On pourra donc rafraichir sa liste de descripteur, et donc lui permettre de surveiller la socket en écriture, et éventuellement écrire les données si cette socket est prete.
Le problème est que sous windows, l'appel poll est implémenté dans winsock, ce qui a pour effet qu'elle ne peut pas prendre en compte des descripteurs autres que des sockets, et donc pas notre malheureux tube qui permet de réveiller poll quand des données doivent être envoyées.
On pourra dire que je réinvente une ènième fois la roue, mais tout ce fatra me permettra de me concentrer sur les couches de plus haut niveau sans avoir à gerer le reste, et surtout, sans avoir a gérer les complexités d'une bibliothèque plus imposante, qui fait tout toute seule et qui, au final, ne possède pas la petite propriété qui fait que ça marche comme il faut.
Notes
[1] On n'a plus ni télévision ni téléphone (et donc pas d'ADSL) depuis les violences de samedi soir (mise à feu des encombrants et du local poubelles)
le lundi 29 août
Le simulateur de réseau ferroviaire
Bon, je rapelle pour les derniers qui ne suivent pas que je suis plutot fan de tout ce qui touche aux trains, et particulièrement les modélisations, réduites mais fidèles, de la réalité (comprendre : petit train électrique, mais en mieux).
Donc, plus jeune, ça devait être un week-end d'ennui quelconque (oui, papa manu, raconte nous ta désopilante vie !), je m'étais dis qu'avec tous les trucs débiles qu'on pouvait trouver sur le ninternet, je trouverais bien un truc qui simule un train qui avance sur des rails, avec des aiguilles, des signaux, et toutes ces choses qui font que j'aime bien.
