Version 0.4
1) Contenu du ChangeLog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
* added LICENCE, as well as a licence header to each source code file
* added src/core/bits/stdint_types.h to import standard integer types in
a portable way.
* moved pipeline_stage<> from src/core/pipeline.h to
src/core/bits/pipeline_stage.h
* CMakeLists.txt: check for <cstdint> or <tr1/ctsdint> presence, as well
as for the namespace in which standard integer types are declared.
Added _SECURE_SCL_NO_WARNINGS define for MSVC builds.
* src/core/bits/pipeline_stage.h: added bits::concatener<> and
bits::extracter<> to optimize the construction of pipeline stages.
* src/core/CMakeLists.txt: added header files to the source file list;
added the install() commands to install the library.
* src/core/pipeline.h: stageify1/2 have been renamed stage(). They now
construct the pipeline_stage<> using bits::concatener<> and
bits::extracter<> [BREAKING CHANGE]
* src/core/security_sha_digest.h: empty collections may implement
iterators that cannot be dereferenced (depending on the library vendor)
[BUG CORRECTION]
* src/ekogen_config.h.in: added the macros to support the use of
src/core/bits/stdint_types.h
* test/pipeline.cpp: added tests to verify the construction of optimized
pipeline_stage objects.
* test/security.cpp: logging the ekogen library version in the
corresponding unit test. |
2) Construction de pipeline
Les fonctions ekogen::stageify1() et ekogen::stageify2() ont été renommées en ekogen::stage() (deux overload) afin de simplifier le code client.
La construction des pipelines a été améliorée. ekogen::stage() renvoie une instance de ekogen::bits::pipeline_stage<F1,F2>(), ou F1 et F2 sont des callables ; une version spécialisée ou F2 = ekogen::bits::nulltype existe, pour générer des pipeline à un élément. Les pipelines sont ensuite composés avec des appels successifs à la fonction stage(), ou via un opérateur | surchargé.
Ainsi, dans la version 0.3, (stage(f1) | stage(f2)) renvoie un pipeline_stage<pipeline_stage<F1,nulltype>,pipeline_stage<F2,nulltype> >. La nouvelle version va plus loin - elle est capable de détecter les "trous" (nulltype) dans les pipeline_stage<> considérés, et adapte le fonctionnement de stage() et de l'opérateur | en conséquence. Du coup, l'expression (stage(f1) | stage(f2)) renvoie maintenant une instance de pipeline_stage<F1,F2>.
Dans le cas ou un "trou" doit être rempli, l'instance construite peut "bouger" les fonctions, tout en respectant l'ordre dans lequel elles sont ajoutées. Les règles suivantes ont été implémentées (entre crochet, la version naîve, implémentée dans la version 0.3 de la librairie):
* operator|(ps<F1,F2>, F3) est équivalent à stage(ps<F1,F2>, F3)
* stage(F1) ==> ps<F1,null> [ ps<F1,null> ]
* stage(F1,F2) ==> ps<F1,F2> [ ps<F1,F2> ]
* stage(ps<F1,F2>) ==> ps<F1,F2> [ ps<ps<F1,F2>,null> ]
* stage(F1) | stage(F2) ==> ps<F1,F2> [ ps<ps<F1,null>,ps<F2,null>> ]
* stage(F1) | F2 ==> ps<F1,F2> [ ps<ps<F1,null>,F2> ]
* stage(F1) | F2 | F3 ==> ps<ps<F1,F2>,F3> [ ps<ps<ps<F1,null>,F2>,F3> ]
* stage(F1) | F2 | stage(F3) ==> ps<ps<F1,F2>,F3> [ ps<ps<ps<F1,null>,F2>,ps<F3,null>> ]
* stage(F1,F2) | stage(F3) ==> ps<ps<F1,F2>,F3> [ ps<ps<F1,F2>,ps<F3,null>> ]
* stage(F1) | stage(F2,F3) ==> ps<ps<F1,F2>,F3> [ ps<ps<F1,null>, ps<F2,F3> ]
On voit clairement l'amélioration sur la profondeur du code généré (non pas que ça posait des problèmes au runtime ; tout ou presque est inliné ; mais c'est quand même beaucoup plus propre et plus logique).
pipeline_stage<> n'est pas censé être utilisé tel quel. Il est bien évidemment possible d'évaluer l'expression définie (l'instance créée est une fonction unaire), voire d'écrire un code ressemblant à :
1 2
|
std::transform(in.begin(), in.end(), out.begin(), (stage(F1) | F2 | F3 | F4)); |
La classe ekogen::pipeline<> a été créée pour manipuler le pipeline résultant. Elle s'utilise ainsi :
ekogen::pipeline<R(A)> p(stage(F1) | F2 | ... | Fn);
* R est bits::callable_traits<Fn>::result_type
* A est bits::callable_traits<F1>::argument_type
Fi peut être un foncteur (qui doit alors hériter de std::unary_function<>) ou un pointeur sur fonction (j'ai oublié de traiter le cas des fonctions membres ; oups).
Il y a bien évidemment des améliorations à faire, mais l'interface ne devrait plus évoluer de manière significative. ekogen::pipeline<> pourrait être étendu (un opérateur () prenant en paramètres trois itérateurs (infirst, inlast, outfirst) pourrait avoir un intérêt), et la construction d'un pipeline pourrait être simplifiée encore, de manière à pouvoir écrire
ekogen::pipeline<R(A)> p = stage(F1) | ... | Fn;
Plutôt que de passer systématiquement par le constructeur.
Partager