Dans le cadre de la réalisation d'un ostream de log qui sera
utilisé dans un contexte multithread, je me suis défini un
streambuf qui mémorise dans des vecteurs (dans des TSS/TLS) ce
qui circule dans chaque thread.
Jusque là, tout va bien. Les articles de James m'ayant bien
mis sur la voie.
Et puis par curiosité, je suis allé voir ce qui se faisait
ailleurs. Sur codesearch de google, je suis tombé sur un code
répondant à la même question. Dans les différences notables,
il y en a une qui m'a intriguée : la mise à jour des pointeurs
de la /put area/ avec setp(), pbump(), etc.
Du coup, je me suis posé la question "mais est-ce bien
nécessaire" ? Si je ne m'abuse, ces pointeurs servent à tout
ce qui est seekp/tellp. Ce qui fait que dans mon contexte de
logs (qui en plus se conclut par un appel à une fonction
variadique d'ACE), je n'en vois pas trop l'intérêt. D'autant
que je trouverait bizarre d'obtenir des valeurs différentes
suivant le thread qui utilise ces fonctions.
Dans le cadre de la réalisation d'un ostream de log qui sera
utilisé dans un contexte multithread, je me suis défini un
streambuf qui mémorise dans des vecteurs (dans des TSS/TLS) ce
qui circule dans chaque thread.
Jusque là, tout va bien. Les articles de James m'ayant bien
mis sur la voie.
Et puis par curiosité, je suis allé voir ce qui se faisait
ailleurs. Sur codesearch de google, je suis tombé sur un code
répondant à la même question. Dans les différences notables,
il y en a une qui m'a intriguée : la mise à jour des pointeurs
de la /put area/ avec setp(), pbump(), etc.
Du coup, je me suis posé la question "mais est-ce bien
nécessaire" ? Si je ne m'abuse, ces pointeurs servent à tout
ce qui est seekp/tellp. Ce qui fait que dans mon contexte de
logs (qui en plus se conclut par un appel à une fonction
variadique d'ACE), je n'en vois pas trop l'intérêt. D'autant
que je trouverait bizarre d'obtenir des valeurs différentes
suivant le thread qui utilise ces fonctions.
Dans le cadre de la réalisation d'un ostream de log qui sera
utilisé dans un contexte multithread, je me suis défini un
streambuf qui mémorise dans des vecteurs (dans des TSS/TLS) ce
qui circule dans chaque thread.
Jusque là, tout va bien. Les articles de James m'ayant bien
mis sur la voie.
Et puis par curiosité, je suis allé voir ce qui se faisait
ailleurs. Sur codesearch de google, je suis tombé sur un code
répondant à la même question. Dans les différences notables,
il y en a une qui m'a intriguée : la mise à jour des pointeurs
de la /put area/ avec setp(), pbump(), etc.
Du coup, je me suis posé la question "mais est-ce bien
nécessaire" ? Si je ne m'abuse, ces pointeurs servent à tout
ce qui est seekp/tellp. Ce qui fait que dans mon contexte de
logs (qui en plus se conclut par un appel à une fonction
variadique d'ACE), je n'en vois pas trop l'intérêt. D'autant
que je trouverait bizarre d'obtenir des valeurs différentes
suivant le thread qui utilise ces fonctions.
Si tu veux des sorties bufferisées, il faut gerer les pointeurs.
Sinon, ce n'est pas la peine.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup. (Sous Unix, l'écriture est
garantie atomique, au moins jusqu'une certaine taille, et avec
les bons paramètres en ouverture, elle est aussi garantie à la
fin de fichier.) Dans ce cas-là, le plus simple, c'est de
simplement faire un push_back() à chaque appel d'overflow(). On
pourrait bien cependant préférer l'utilisation du vector comme
un buffer ; dans ce cas-là, on l'agrandit dans overflow(), et on
met les pointeurs. Quelque chose du genre :
[...]
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
Si tu veux des sorties bufferisées, il faut gerer les pointeurs.
Sinon, ce n'est pas la peine.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup. (Sous Unix, l'écriture est
garantie atomique, au moins jusqu'une certaine taille, et avec
les bons paramètres en ouverture, elle est aussi garantie à la
fin de fichier.) Dans ce cas-là, le plus simple, c'est de
simplement faire un push_back() à chaque appel d'overflow(). On
pourrait bien cependant préférer l'utilisation du vector comme
un buffer ; dans ce cas-là, on l'agrandit dans overflow(), et on
met les pointeurs. Quelque chose du genre :
[...]
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
Si tu veux des sorties bufferisées, il faut gerer les pointeurs.
Sinon, ce n'est pas la peine.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup. (Sous Unix, l'écriture est
garantie atomique, au moins jusqu'une certaine taille, et avec
les bons paramètres en ouverture, elle est aussi garantie à la
fin de fichier.) Dans ce cas-là, le plus simple, c'est de
simplement faire un push_back() à chaque appel d'overflow(). On
pourrait bien cependant préférer l'utilisation du vector comme
un buffer ; dans ce cas-là, on l'agrandit dans overflow(), et on
met les pointeurs. Quelque chose du genre :
[...]
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup.
Dans ce cas-là, le plus simple, c'est de simplement faire un
push_back() à chaque appel d'overflow(). On pourrait bien
cependant préférer l'utilisation du vector comme un buffer ;
dans ce cas-là, on l'agrandit dans overflow(), et on met les
pointeurs. Quelque chose du genre :
int
LogStreambuf::overflow(
int ch )
{
size_t current = myBuffer.size() ;
myBuffer.push_back( ch ) ;
myBuffer.resize( myBuffer.capacity() ) ;
setp( &myBuffer[ 0 ] + current,
&myBuffer[ 0 ] + myBuffer.size() ) ;
return ch ;
}
(J'ai negligé le cas où ch vaut EOF, pour simplifier.)
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup.
Dans ce cas-là, le plus simple, c'est de simplement faire un
push_back() à chaque appel d'overflow(). On pourrait bien
cependant préférer l'utilisation du vector comme un buffer ;
dans ce cas-là, on l'agrandit dans overflow(), et on met les
pointeurs. Quelque chose du genre :
int
LogStreambuf::overflow(
int ch )
{
size_t current = myBuffer.size() ;
myBuffer.push_back( ch ) ;
myBuffer.resize( myBuffer.capacity() ) ;
setp( &myBuffer[ 0 ] + current,
&myBuffer[ 0 ] + myBuffer.size() ) ;
return ch ;
}
(J'ai negligé le cas où ch vaut EOF, pour simplifier.)
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup.
Dans ce cas-là, le plus simple, c'est de simplement faire un
push_back() à chaque appel d'overflow(). On pourrait bien
cependant préférer l'utilisation du vector comme un buffer ;
dans ce cas-là, on l'agrandit dans overflow(), et on met les
pointeurs. Quelque chose du genre :
int
LogStreambuf::overflow(
int ch )
{
size_t current = myBuffer.size() ;
myBuffer.push_back( ch ) ;
myBuffer.resize( myBuffer.capacity() ) ;
setp( &myBuffer[ 0 ] + current,
&myBuffer[ 0 ] + myBuffer.size() ) ;
return ch ;
}
(J'ai negligé le cas où ch vaut EOF, pour simplifier.)
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
On 7 avr, 15:08, James Kanze wrote:Si tu veux des sorties bufferisées, il faut gerer les pointeurs.
Sinon, ce n'est pas la peine.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup. (Sous Unix, l'écriture est
garantie atomique, au moins jusqu'une certaine taille, et avec
les bons paramètres en ouverture, elle est aussi garantie à la
fin de fichier.) Dans ce cas-là, le plus simple, c'est de
simplement faire un push_back() à chaque appel d'overflow(). On
pourrait bien cependant préférer l'utilisation du vector comme
un buffer ; dans ce cas-là, on l'agrandit dans overflow(), et on
met les pointeurs. Quelque chose du genre :
[...]
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
Or, à cause d'une bibliothèque externe que j'intègre, et qui logge
dans ... std:::cout, je voulais limiter les indirections. Et donc
proposer un unique streambuf qui contient des vecteurs dans des TSS.
Je ne vois pas comment bufferiser plus : mon streambuf forcé dans
std::cout ne pouvant être bufferisé vu que les Xpptr() ne peuvent pas
être directement locaux à des threads.
On 7 avr, 15:08, James Kanze <james.ka...@gmail.com> wrote:
Si tu veux des sorties bufferisées, il faut gerer les pointeurs.
Sinon, ce n'est pas la peine.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup. (Sous Unix, l'écriture est
garantie atomique, au moins jusqu'une certaine taille, et avec
les bons paramètres en ouverture, elle est aussi garantie à la
fin de fichier.) Dans ce cas-là, le plus simple, c'est de
simplement faire un push_back() à chaque appel d'overflow(). On
pourrait bien cependant préférer l'utilisation du vector comme
un buffer ; dans ce cas-là, on l'agrandit dans overflow(), et on
met les pointeurs. Quelque chose du genre :
[...]
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
Or, à cause d'une bibliothèque externe que j'intègre, et qui logge
dans ... std:::cout, je voulais limiter les indirections. Et donc
proposer un unique streambuf qui contient des vecteurs dans des TSS.
Je ne vois pas comment bufferiser plus : mon streambuf forcé dans
std::cout ne pouvant être bufferisé vu que les Xpptr() ne peuvent pas
être directement locaux à des threads.
On 7 avr, 15:08, James Kanze wrote:Si tu veux des sorties bufferisées, il faut gerer les pointeurs.
Sinon, ce n'est pas la peine.
Ce que j'ai trouvé utile dans un log, c'est d'effectivement
collecter tout un enrégistrement dans un std::vector<> (par
exemple), puis de l'écrire d'un coup. (Sous Unix, l'écriture est
garantie atomique, au moins jusqu'une certaine taille, et avec
les bons paramètres en ouverture, elle est aussi garantie à la
fin de fichier.) Dans ce cas-là, le plus simple, c'est de
simplement faire un push_back() à chaque appel d'overflow(). On
pourrait bien cependant préférer l'utilisation du vector comme
un buffer ; dans ce cas-là, on l'agrandit dans overflow(), et on
met les pointeurs. Quelque chose du genre :
[...]
Ça reduit les appels virtuels, etc.
Aussi, il peut être intéressant d'avoir un streambuf par thread,
afin de ne pas avoir besoin des locks, ou au moins limiter le
temps qu'on les tient.
OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
Or, à cause d'une bibliothèque externe que j'intègre, et qui logge
dans ... std:::cout, je voulais limiter les indirections. Et donc
proposer un unique streambuf qui contient des vecteurs dans des TSS.
Je ne vois pas comment bufferiser plus : mon streambuf forcé dans
std::cout ne pouvant être bufferisé vu que les Xpptr() ne peuvent pas
être directement locaux à des threads.
On Apr 7, 4:42 pm, Luc Hermitte wrote:OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
On Apr 7, 4:42 pm, Luc Hermitte <luc.hermi...@gmail.com> wrote:
OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
On Apr 7, 4:42 pm, Luc Hermitte wrote:OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
On Apr 7, 4:42 pm, Luc Hermitte wrote:OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
On Apr 7, 4:42 pm, Luc Hermitte <luc.hermi...@gmail.com> wrote:
OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
On Apr 7, 4:42 pm, Luc Hermitte wrote:OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
On Apr 7, 4:42 pm, Luc Hermitte wrote:OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
On Apr 7, 4:42 pm, Luc Hermitte <luc.hermi...@gmail.com> wrote:
OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
On Apr 7, 4:42 pm, Luc Hermitte wrote:OK. Merci pour ta réponse. J'ai passé un peu de temps à la murir, et
je pense avoir saisi maintenant.
Je comprends mieux du coup certains autres choix de l'autre code que
j'avais trouvé -- en gros il y a une classe "point d'accès" qui
renvoie un ostream localisé au thread courant (TSS).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
On Apr 8, 11:09 am, Michel Decima wrote:(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la reste
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
On Apr 8, 11:09 am, Michel Decima <michel.dec...@orange-ft.com> wrote:
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la reste
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
On Apr 8, 11:09 am, Michel Decima wrote:(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la reste
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la rest e
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la rest e
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la rest e
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
On 9 avr, 09:37, James Kanze wrote:(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la re ste
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
En effet. Ceci dit, avec "TSS c++" google envoie direct sur le
papier de Schmidt -- qui correspond à l'implémentation que
j'utilise
On 9 avr, 09:37, James Kanze <james.ka...@gmail.com> wrote:
(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la re ste
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
En effet. Ceci dit, avec "TSS c++" google envoie direct sur le
papier de Schmidt -- qui correspond à l'implémentation que
j'utilise
On 9 avr, 09:37, James Kanze wrote:(C'est quoi, TSS ?)
Surement une abbréviation de Thread Specific Storage.
Voilà. J'avais à peu près déviné le « thread », mais la re ste
m'a laissé perplexe, et Google donnait surtout des entrées pour
« toxic shock syndrome » (et j'étais assez sûr que ce n'était
pas ça qu'il voulais dire).
En effet. Ceci dit, avec "TSS c++" google envoie direct sur le
papier de Schmidt -- qui correspond à l'implémentation que
j'utilise