OVH Cloud OVH Cloud

fstream et lockf

15 réponses
Avatar
ricky
bonjour,

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d
anciens compilo. Le tout est suivi d'un lockf(descripteur, ...) qui est
le but de l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases sur
les FILE, ce qui est un peu hors norme...

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream
par des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?

cordialement

10 réponses

1 2
Avatar
Michael DOUBEZ
bonjour,

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d
anciens compilo. Le tout est suivi d'un lockf(descripteur, ...) qui est
le but de l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases sur
les FILE, ce qui est un peu hors norme...

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream
par des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?


Il n'y a pas d'opération standard qui permette de placer un verrou sur
un fichier donc il n'y a pas lieu de s'inquiéter d'une solution de
remplacement tant que tu restes sur l'implémentation GNU/POSIX de la STL.

Maintenant, si tu as besoin de portabilité, il n'y a que la compilation
conditionnelle (ou oublier les locks).

Michael

Avatar
James Kanze
ricky wrote:

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d
anciens compilo. Le tout est suivi d'un lockf(descripteur, ...) qui est
le but de l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases sur
les FILE, ce qui est un peu hors norme...


Ça n'a rien à voir avec FILE; le fd renvoyé, c'est le fd du
niveau Posix.

La norme n'a jamais supportée cette fonction, du fait que ce
n'est pas disponible sur des systèmes non-Posix. (Bien que...
tout système a besoin de quelque chose qui en joue la rôle. La
norme aurait très bien pû exiger un typedef pour le type, et une
fonction qui le renvoie.) N'empèche que c'est une extension
quasi-standard dans le monde des systèmes Posix, un peu comme
fileno() sur FILE (qui n'est pas standard C non plus, mais fait
partie de la norme Posix). Autant que je sache, il n'y a que g++
qui ne l'implémente pas.

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream
par des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?


La seule vraie solution propre, c'est de réécrire filebuf
toi-même, en l'ajoutant. Elle fait logiquement partie du
« binding » Posix du C++, mais dans la mesure que personne ne
s'occupe de ce binding, on ne risque pas d'avoir un document
officiel pour le confirmer.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Jean-Marc Bourguet
ricky writes:

bonjour,

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d anciens
compilo. Le tout est suivi d'un lockf(descripteur, ...) qui est le but de
l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases sur
les FILE, ce qui est un peu hors norme...

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream par
des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?


Une alternative est d'implementer tes propres streams qui fournissent
l'interface que tu veux en plus de l'interface normale. Il y a un exemple
dans la FAQ.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Michel Decima
bonjour,

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d
anciens compilo. Le tout est suivi d'un lockf(descripteur, ...) qui est
le but de l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases sur
les FILE, ce qui est un peu hors norme...

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream
par des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?


Pour garder la fonctionnalite, avec un impact minimum sur le code,
je remplacerais le fstream par un flux maison qui encapsule un FILE*,
en partant de ce qu'on trouve dans la FAQ section 27.3
http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/#flux_entree_sortie

Au final, ca devrait donner quelque chose comme ca:

void traitementFlux( std::istream& in );

FILE* inFile = fopen("foo.txt", "r");
int inDescr = fileno( cfile );
lockf( inDescr, ... );
iFILEstream input( inFile );
traitementFlux( input );
unlockf( inDescr, ... );
fclose( inFile );

le tout sans traitement d'erreurs, bien entendu. On devrait aussi
pouvoir integrer la gestion du lock dans une classe FILEstream plus
elaboree, ce qui permettrait le unlock dans le destructeur, etc.

Avatar
Michael DOUBEZ
bonjour,

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d
anciens compilo. Le tout est suivi d'un lockf(descripteur, ...) qui
est le but de l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases
sur les FILE, ce qui est un peu hors norme...

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream
par des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?


Pour garder la fonctionnalite, avec un impact minimum sur le code,
je remplacerais le fstream par un flux maison qui encapsule un FILE*,
en partant de ce qu'on trouve dans la FAQ section 27.3
http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/#flux_entree_sortie


Au final, ca devrait donner quelque chose comme ca:

void traitementFlux( std::istream& in );

FILE* inFile = fopen("foo.txt", "r");
int inDescr = fileno( cfile );
lockf( inDescr, ... );
iFILEstream input( inFile );
traitementFlux( input );
unlockf( inDescr, ... );
fclose( inFile );

le tout sans traitement d'erreurs, bien entendu. On devrait aussi
pouvoir integrer la gestion du lock dans une classe FILEstream plus
elaboree, ce qui permettrait le unlock dans le destructeur, etc.




g++ (3.4) propose une extension qui permet de faire cela; cela s'appelle
stdio_filebuf.

Le code peut être repris pour l'incorporer au projet.

Michael


Avatar
ricky
bonjour


g++ (3.4) propose une extension qui permet de faire cela; cela s'appelle
stdio_filebuf.

Le code peut être repris pour l'incorporer au projet.

Michael


merci a tous pour vos reponses

en fait j ai utilise un truc peu elegant mais qui me semble tres rapide
a mettre en place sans changer le code initial...
en fait je rajoute simplement au code initial un FILE* fichier qui
pointe sur le fichier qui sera utilise par le stream .. j ai donc un fd
valide pour ce fichier tout en ne touchant pas a l acces qui etait
utilisé a base de fstream ...

en gros, j ai en meme temps un FILE* et un fstream sur le meme fichier :)

bon je sais, ca va en faire bondir certains mais c est tres economique
comme correction quand on est presse , enfin je pense

@+

Avatar
James Kanze
Michael DOUBEZ wrote:

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d
anciens compilo. Le tout est suivi d'un lockf(descripteur, ...) qui
est le but de l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases
sur les FILE, ce qui est un peu hors norme...

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream
par des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?


Pour garder la fonctionnalite, avec un impact minimum sur le code,
je remplacerais le fstream par un flux maison qui encapsule un FILE*,
en partant de ce qu'on trouve dans la FAQ section 27.3
http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/#flux_entree _sortie

Au final, ca devrait donner quelque chose comme ca:

void traitementFlux( std::istream& in );

FILE* inFile = fopen("foo.txt", "r");
int inDescr = fileno( cfile );
lockf( inDescr, ... );
iFILEstream input( inFile );
traitementFlux( input );
unlockf( inDescr, ... );
fclose( inFile );

le tout sans traitement d'erreurs, bien entendu. On devrait aussi
pouvoir integrer la gestion du lock dans une classe FILEstream plus
elaboree, ce qui permettrait le unlock dans le destructeur, etc.


g++ (3.4) propose une extension qui permet de faire cela; cela s'appelle
stdio_filebuf.


Mais pourquoi cette manie d'utiliser un FILE*. L'extension de
g++, c'est très utile quand on veut travailler avec les
iostream, mais qu'on a du code existant qui utilise des FILE*.
En revanche, il n'y a pas plus de manière « standard »
d'obtenir un file descripteur d'un FILE* que d'un std::filebuf.
La fonction fileno est Posix, et se mappe naturellement (et
traditionnellement) à filebuf::fd() en C++ -- une
implémentation assez irresponsable de ne pas offrir
filebuf::fd() sous Posix pourrait très bien aussi ne pas offrir
fileno().

Personnellement, étant donné que de telles implémentations
existent, la meilleur solution est bien d'écrire ton propre
fdstreambuf ; du coup, ça permettre l'utilisation des iostream
pour des pipe et des sockets aussi. (Mais c'est un peu dommage
d'en être arrivé là).

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
Michael DOUBEZ
Michael DOUBEZ wrote:

j'ai un vieux code qui contient un fstream file suivi d'un tres joli
file.rdbuf()->fd() permettant de recuperer le file descriptor sur d
anciens compilo. Le tout est suivi d'un lockf(descripteur, ...) qui
est le but de l' operation :)

probleme, cela n est faisable que parceque les fstream etaient bases
sur les FILE, ce qui est un peu hors norme...

quelle est la meilleur solution de remplacement ?

la plus evidente et la moins c++ serait amha de rfemplacer les fstream
par des FILE* fichier et hop j'ai mon file descripteur

ou de trouver un bon equivalent de lockf

que me conseilleriez vous?


Pour garder la fonctionnalite, avec un impact minimum sur le code,
je remplacerais le fstream par un flux maison qui encapsule un FILE*,
en partant de ce qu'on trouve dans la FAQ section 27.3
http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/#flux_entree_sortie

Au final, ca devrait donner quelque chose comme ca:

void traitementFlux( std::istream& in );

FILE* inFile = fopen("foo.txt", "r");
int inDescr = fileno( cfile );
lockf( inDescr, ... );
iFILEstream input( inFile );
traitementFlux( input );
unlockf( inDescr, ... );
fclose( inFile );

le tout sans traitement d'erreurs, bien entendu. On devrait aussi
pouvoir integrer la gestion du lock dans une classe FILEstream plus
elaboree, ce qui permettrait le unlock dans le destructeur, etc.


g++ (3.4) propose une extension qui permet de faire cela; cela s'appelle
stdio_filebuf.


Mais pourquoi cette manie d'utiliser un FILE*. L'extension de
g++, c'est très utile quand on veut travailler avec les
iostream, mais qu'on a du code existant qui utilise des FILE*.
En revanche, il n'y a pas plus de manière « standard »
d'obtenir un file descripteur d'un FILE* que d'un std::filebuf.
La fonction fileno est Posix, et se mappe naturellement (et
traditionnellement) à filebuf::fd() en C++ -- une
implémentation assez irresponsable de ne pas offrir
filebuf::fd() sous Posix pourrait très bien aussi ne pas offrir
fileno().


Je suis d'accord avec toi, je lui ai juste signalé qu'il pouvait
reprendre le code (à moins que son soft ne soit pas GPL compliant).
stdio_filebuf s'instancie à partir d'un FILE ou d'un file descriptor;
comme l'OP voulait utiliser lockf, je suppose qu'il utilisera un file
descriptor.

Personnellement, étant donné que de telles implémentations
existent, la meilleur solution est bien d'écrire ton propre
fdstreambuf ; du coup, ça permettre l'utilisation des iostream
pour des pipe et des sockets aussi. (Mais c'est un peu dommage
d'en être arrivé là).


Et pour des ports série.

Michael




Avatar
ricky
bonjour

Mais pourquoi cette manie d'utiliser un FILE*.


oh personnellement je m'adapte :-)
je n'ai aucun préjugé simplement je doit adapter un vieux code a linux,
en minimisant les effets de bord, et sans perdre de temps

En revanche, il n'y a pas plus de manière « standard »
d'obtenir un file descripteur d'un FILE* que d'un std::filebuf.


le open me donne ce qu'il me faut ;)

Personnellement, étant donné que de telles implémentations
existent, la meilleur solution est bien d'écrire ton propre
fdstreambuf ; du coup, ça permettre l'utilisation des iostream
pour des pipe et des sockets aussi. (Mais c'est un peu dommage
d'en être arrivé là).


je suis entierement d'accord avec vous, mais des fois il faut s'adapter
aux imperatifs ;-)


de plus, n'est il pas parfois preferable d'aller au plus rapide (deux
lignes seulement de changees et 5mn de passees) qu'au plus beau quand le
temps manque, ou que le code est tres vieux ?

il est certain que lorsque j'aurai plus de temps, il y a pas mal de
choses que je compte changer mais en attendant, tout doit avancer parfois :)

Avatar
James Kanze
ricky wrote:
Mais pourquoi cette manie d'utiliser un FILE*.


oh personnellement je m'adapte :-)
je n'ai aucun préjugé simplement je doit adapter un vieux code a linu x,
en minimisant les effets de bord, et sans perdre de temps

En revanche, il n'y a pas plus de manière « standard »
d'obtenir un file descripteur d'un FILE* que d'un std::filebuf.


le open me donne ce qu'il me faut ;)


Qui de Posix, mais non du C ni du C++. Qui est un autre
standard, mais qui officiellement n'est pas sujet de ce forum.
Officieusement, évidemment, il s'avère que certains
participants -- dont moi-même -- le connaissent aussi, et en
parle de temps en temps.

Et mes commentaires s'adressaient non seulement à ton problème
précis, mais aussi aux certains regrets généraux que j'ai :

-- Que la norme n'a pas fourni un « hook » pour ce genre de
chose. Rien ne l'aurait empéché d'ajouter un tyepdef
system_specific_low_level_file_handle_t, et quelques
fonctions pour le connecter à un filebuf ou en recupérer
celui dont se sert le filebuf. Ensuite, évidemment, tout ce
que je fais avec ce type dépend de l'implémentation, mais
c'est à moi de décider si c'est un problème ou non.

-- Que des implémentations sous Unix (une, au moins) se sont
éloignées des extentions standard « de facto » de ces
systèmes, et ont ôté la fonction filebuf::fd().

Personnellement, étant donné que de telles implémentations
existent, la meilleur solution est bien d'écrire ton propre
fdstreambuf ; du coup, ça permettre l'utilisation des iostream
pour des pipe et des sockets aussi. (Mais c'est un peu dommage
d'en être arrivé là).


je suis entierement d'accord avec vous, mais des fois il faut s'adapter
aux imperatifs ;-)

de plus, n'est il pas parfois preferable d'aller au plus rapide (deux
lignes seulement de changees et 5mn de passees) qu'au plus beau quand le
temps manque, ou que le code est tres vieux ?


Tout dépend. La bonne solution, c'est celle qui remplit les
impératifs et qui est la moins chère à la longue. Le « à la
longue » est important : s'il y a déjà un remplacement dans
les tuyaux, et c'est juste pour faire survivre le programme
actuel jusqu'à ce qu'il arrive, les choix ne sont pas les même
que s'il va falloir vivre avec le code encore des années. De
même, on a parfois des impératifs du genre, il faut que le
programme aille en production hier. Si c'est vraiment le cas, on
fait ce qu'on peut, en espérant de se ratrapper plus tard.
(C'est pourquoi on a des branches dans les systèmes de gestion
des sources. On bricole une correction on ne peut plus vite sur
la branche de maintenance, et on cherche une solution propre
pour la branche de développement. Ce qui fait qu'on résoud le
même problème deux fois, des façons différentes. Mais souvent,
c'est la seule solution qui remplit les impératifs de temps et
ne coûte pas trop cher à la longue.)

il est certain que lorsque j'aurai plus de temps, il y a pas mal de
choses que je compte changer mais en attendant, tout doit avancer parfois :)


Je comprends bien. Je travaille dans l'industrie aussi:-).

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


1 2