• Aucun résultat trouvé

2.1 Arch´ etype de donn´ ees

2.1.2 Interface compilable

a partir de la graine 123456789. Le param`etre 19 pr´ecise que l’on consid`ere l’ensemble du corps pour g´en´erer les ´el´ements al´eatoires. Le reste des calculs est identique `a l’exemple pr´ec´edent.

2.1.2 Interface compilable

Comme nous l’avons vu dans la section pr´ec´edente, le premier rˆole de l’arch´etype est de fixer le mod`ele de base des corps finis. Nous avons aussi vu que ce mod`ele comportait trois types de donn´ees (domaines de calcul, ´el´ements, g´en´erateurs al´eatoires). Chacune de ces structures de donn´ees doit respecter son propre arch´etype afin d’offrir la g´en´ericit´e compl`ete des implantations de corps finis.

Une autre caract´eristique de l’arch´etype est de servir d’interface de donn´ees pour proposer des instances compil´ees des codes de la biblioth`eque LinBox. L’int´erˆet de proposer une telle inter-face est de pouvoir fournir des codes compil´es qui soient robustes et facilement reconfigurables.

L’approche classique en C++ pour d´efinir de telles interfaces est d’utiliser une hi´erarchie de classes bas´ee sur une classe de base abstraite [80,§12.4.2]. En effet, nous avons vu dans la partie 1.1.2 que les tables virtuelles permettent d’acc´eder aux fonctions `a partir du type dynamique des objets (voir figure 1.3). Toutefois, la construction d’objets abstraits reste impossible. De ce fait, ces objets ne peuvent exister qu’au travers de pointeurs ou de r´ef´erences sur un objet d´erivant de la classe abstraite. L’utilisation d’interfaces abstraites comme param`etres des fonctions n´ecessite de manipuler tous les objets de fa¸con dynamique, ce qui est incompatible avec la d´efinition de codestemplate du fait que l’allocation des ´el´ements est faite de fa¸con statique pour des raisons de performance.

Une alternative propos´ee par la biblioth`eque LinBox est d’encapsuler ces interfaces abstraites

`

a l’int´erieur d’objets compilables. Le but de ces objets est de g´erer l’ensemble des allocations m´emoire des objets abstraits tout en conservant le rˆole d’interface de donn´ees. Pour cela, la gestion m´emoire est ici relay´ee au constructeur et au destructeur de la classe alors que le poly-morphisme est assur´e par des indirections sur les fonctions de l’interface abstraite. L’utilisation de cette interface comme instanciation des codes template permet de fournir une instance de code compilable sans avoir `a modifier les codes g´en´eriques.

Fig. 2.2 – Structure de l’arch´etype des corps finis.

La figure 2.2 d´ecrit la structure d’une interface de donn´ees compilable. Cette structure se d´ecoupe en trois modules. Tout d’abord on peut distinguer au plus bas niveau les classes Abs-tract et Envelope. La classe Abstract d´efinit l’interface abstraite, en proposant un mod`ele de fonction virtuelle pure pour toutes les fonctions du mod`ele de base. La classe Envelope permet de synchroniser l’ensemble des corps finis conformes au mod`ele de base avec l’interface

2.1. Arch´etype de donn´ees 33 abstraite. Plus pr´ecis´ement, cette classe permet d’int´egrer de fa¸con g´en´erique des fonctions d’al-locations m´emoire n´ecessaires `a la manipulation d’objets abstraits. Cette classe est optionnelle si l’on utilise directement une implantation de corps finis qui d´erive de l’interface abstraite et qui propose l’ensemble des fonctions d’allocations m´emoire. La classeArchetyped´efinit `a la fois le mod`ele de base des corps finis et l’objet compilable int´egrant l’interface abstraite. L’int´egration de l’interface abstraite se fait au travers d’un pointeur de donn´ees. L’instanciation de ce pointeur par un objet d´eriv´e de l’interface abstraite permet donc de fixer le polymorphisme dynamique de l’interface. L’utilisation de l’enveloppe pour instancier ce pointeur permet d’assurer le bon comportement des allocations m´emoire pour toutes les implantations de corps finis.

héritage

Fig. 2.3 – Code pour une interface abstraite compilable.

Nous nous int´eressons maintenant aux d´etails d’implantation de l’arch´etype de donn´ees des corps finis. La figure 2.3 d´ecrit les diff´erents m´ecanismes C++ utilis´es pour obtenir une interface de donn´ees compilable. La classe FieldArchetype int`egre la classe FieldAbstract au travers du pointeur de donn´ees _ptr. Afin de conserver le polymorphisme de l’interface abstraite, le constructeur est g´en´erique sur le type de corps fini. La construction d’un arch´etype sur un corps fini concret entraˆıne l’allocation du pointeur_ptr au travers de l’enveloppe.

La redirection de toutes les fonctions de l’arch´etype vers les fonctions de l’interface abstraite au travers du pointeur _ptr permet de rendre l’arch´etype polymorphe. Ainsi, l’appel de la fonctionptr->function()dans la d´efinition de la fonctionfunction()de l’arch´etype entraˆıne l’appel de la fonction _field.function rattach´ee au corps d’instanciation de l’arch´etype. On remarque que ce type d’appel comporte trois niveaux d’indirection : pointeur FieldAbstract, tables virtuelles de FieldAbstract, FieldEnvelope. L’enveloppe peut ne pas ˆetre consid´er´ee comme une indirection car les m´ethodes d’inlining des compilateurs absorbent en partie les d´efinitions par appel de fonctions.

La partie la plus importante de cet arch´etype concerne la gestion m´emoire des objets abs-traits. En dehors de sa construction, l’arch´etype n’a aucune connaissance du type de corps sur

lequel il agit. Il ne connaˆıt en fait que l’interface abstraite. Afin de permettre `a l’arch´etype de cr´eer des copies de lui-mˆeme, une m´ethode classique des interfaces abstraites [80, §15.6.2] est de proposer une fonctionclone()d´efinie dans l’interface abstraite qui permet de construire des copies dynamiques des objets abstraits. Grˆace `a cette fonction, il est alors possible de cr´eer des objets abstraits sans connaˆıtre leur type dynamique. Le constructeur par copie de l’arch´etype utilise donc cette fonction pour cr´eer des copies d’objets abstraits.