OVH Cloud OVH Cloud

comment retourner une variable synchronisée

29 réponses
Avatar
pasde.hcyrano.spam
bonsoir,

j'ai un probleme vraiment bete

inline void POSIXThread::isInterrupted(bool& ret) {

mutex.lock();
ret = _interrupt;
mutex.unlock();

}

me parais vraiment "bouzin"

j'aimerai une signature du genre :

bool POSIXThread::isInterrupted();

comment puis faire, cela doit etre simple, mais je ne vois pas :-(

merci de votre aide

--
Bruno Causse
http://perso.wanadoo.fr/othello

9 réponses

1 2 3
Avatar
kanze
Bruno CAUSSE wrote:
dans l'article
, kanze à
a écrit le 14/03/06 8:45 :

Ça veut dire quoi, état réel ? La valeur utilisée correspond
bien à l'état réel lors que la variable a été lue. Dans la
mesure où on modifie la variable de façon asynchrone par
ailleurs, on ne peut guère démander plus.


Une question a la con :-)

synchronisé un booleen cela a t'il un sens?

Meme si il est lu et ecris en meme temps, cela pose t'il
probleme (cas particulier du booleen)?


Peut-être. Sur des hardwares anciens, et certains hardwares
simple aujourd'hui, ce n'est probablement pas nécessaire ; un
coup de volatile (pour empécher les optimisations du
compilateur) suffira. Dès qu'on a des pipelines, des mémoire
cache, et d'autres trucs de ce genre, il faut bien faire quelque
chose : sur un Sparc, par exemple, il faudrait une instruction
membar en plus. Des requêtes de synchronisation, genre
pthread_mutex_wait, sont garanties de contenir les instructions
supplémentaires qu'il faut pour assurer la synchronisation de la
mémoire du thread qui les appelle. Et un compilateur compatible
avec les systèmes qui offrent ces requêtes les traitera comme
une limite dans l'optimisation ; du coup, le volatile ne sert
plus a rien.

--
James Kanze GABI Software
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
kanze
Sylvain wrote:
kanze wrote on 14/03/2006 08:45:

entre quel *temps* ?


Entre le temps qu'il a lu la valeur, et le temps qu'il en
utilise la copie, non ?


c'est ce que j'anticipe et crains, car la valeur _utilisée_
n'a plus aucune garantie d'être l'état réel.


Ça veut dire quoi, état réel ? [...]


tu as un problème avec ce qui n'est pas formulé par toi avec
tes mots ?


J'ai un problème avec ce qui est flou, et qui ne donne pas assez
de précisions pour pouvoir commencer à coder. La question
reste : dans cette contexte, qu'est-ce qu'on entend par « l'état
réel » ? Je n'arrive pas à en donner une signification dans
cette contexte -- a priori, il y a autant d'« états réels »
qu'il y a de threads, et le mot n'a de sens pour un thread donné
que dans la mesure où il accède à la variable. (Et encore -- si
plusieurs threads accèdent sans synchronisation, on a en général
un état indéfini.)

--
James Kanze GABI Software
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
kanze
Sylvain wrote:
Arnaud Meurgues wrote on 14/03/2006 13:46:

Je crois qu'il veut surtout dire que « état réel » a une
sémantique floue en environnement multithread ou parallèle
et qu'il est bon de se poser à soi-même cette question afin
d'être sûr de savoir ce que l'on veut.


<troll>
est-ce propre à ce groupe ou seulement l'habitude de certains
que de faire de la sémantique pour la sémantique ?


C'est le propre de certains d'entre nous de vouloir écrire un
code robuste, en comprenant ce qu'on fait.

quelle est "cette" question que soi-même devrait se poser ?


Pour commencer, qu'est-ce qu'on essaie de faire ?

</troll>

btw, perso je ne "veux" rien et je n'aurais surement pas codé
une fonction qui fournit une information inutile (par durée de
vie incertaine);


La fonction, telle qu'elle est codée, est très utile. Elle
renvoie la valeur de la variable au moment t où elle est
appelée. À condition qu'il y a une synchronisation semblable
lors de l'écriture, elle remplit bien la fonction qu'elle est
sensée remplir.

cela n'empêchait pas d'alerter l'auteur sur les risques de non
pertinence de sa variable d'état; cela à été dit.


Quelles risques ? Tu ne les as toujours pas précisées.

Note bien que s'il renvoiait la variable par référence, la
situation serait différente. Mais ce n'était pas le cas.

--
James Kanze GABI Software
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
kanze
Arnaud Meurgues wrote:
Bruno CAUSSE wrote:

je ne connais pas scoped_lock(), je vais voir cela.


Ce n'est pas une classe C++ standard.
James parle du principe RAII. RAII veut dire resource
acquisition is initialisation et c'est un idiome très utilisé
en C++.


Tout à fait. Le nom que j'ai utilisé et celui de Boost, mais il
me semble convenir en général -- et l'intention était qu'il soit
compris comme le nom du concepte, et pas qu'on pense qu'il
fallait absolument utiliser Boost (bien qu'utiliser Boost n'est
pas une mauvaise idée non plus).

--
James Kanze GABI Software
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
Bruno CAUSSE
dans l'article , kanze à
a écrit le 15/03/06 8:39 :

du coup, le volatile ne sert
plus a rien.


cela je l'ai compris en lisant vos postes :-)

Je l'utilisais beaucoup quand je codais en java.

C'est peu être utile pour les prog MultiThread tournant sur un mono core (et
encore autant coder avec les mutex c'est aussi simple)

Avatar
Sylvain
kanze wrote on 15/03/2006 08:46:

J'ai un problème avec ce qui est flou, et qui ne donne pas assez
de précisions pour pouvoir commencer à coder.


ah c'est ça ! alors voila il faut une fonction "isInterrupted".
prêt à coder, partez. et pas de mauvaise foi sur un supposé flou, s'il
existait tu l'aurais déjà signalé.

La question reste : dans cette contexte, qu'est-ce qu'on
entend par « l'état réel » ?


"par là pas grand chose".

Je n'arrive pas à en donner une signification dans
cette contexte


et ça reste vivable ?

a priori, il y a autant d'« états réels »
qu'il y a de threads


là j'aurais dit "états potentiellement distincts".

et le mot n'a de sens pour un thread donné
que dans la mesure où il accède à la variable.


s'il n'y accède pas, elle n'est pas d'état du tout ?
je ne pensais pas qu'un objet perdait ses membres non consultés aussi
facilement -- si le point est on se tape de l'état de cette variable là,
oui (et merci pour cette grande clarification).

(Et encore -- si plusieurs threads accèdent sans
synchronisation, on a en général un état indéfini.)


c'est ce que j'ai énoncé il y a 15 posts et que tu refuses de lire.

Sylvain.

Avatar
Sylvain
kanze wrote on 15/03/2006 08:51:

est-ce propre à ce groupe ou seulement l'habitude de certains
que de faire de la sémantique pour la sémantique ?


C'est le propre de certains d'entre nous de vouloir écrire un
code robuste, en comprenant ce qu'on fait.


on écrit du code là, ici, maintenant, dans ces conditions gélatineuses
sur l'usage de tel adjectif ou la place du'une virgule ?

quelle est "cette" question que soi-même devrait se poser ?


Pour commencer, qu'est-ce qu'on essaie de faire ?


ben en ce moment, à part enculer les mouches, je vois pas ce que "on"
essaie de faire.

btw, perso je ne "veux" rien et je n'aurais surement pas codé
une fonction qui fournit une information inutile (par durée de
vie incertaine);


La fonction, telle qu'elle est codée, est très utile. Elle
renvoie la valeur de la variable au moment t où elle est
appelée. À condition qu'il y a une synchronisation semblable
lors de l'écriture, elle remplit bien la fonction qu'elle est
sensée remplir.


incorrect!

1- elle renvoie la valeur qu'à eu la variable "_interrupt" au moment où
elle a été accedé dans la méthode "isInterrupted"; entre cet instant
d'évaluation et le moment "t" où la méthode "isInterrupted" est appellée
(tu as bien dit "la fonction ... est appelée"), il s'écoule un temps
indéterminable d'après les informations fournis - par exemple si le lock
est posé par une autre méthode exécutée par un autre thread que celui
réalisant cet appel à "isInterrupted", le mutex.lock() suspendra cette
exécution, avec dans le pire des cas un deadlock qui annihilira ton "t"
qui ne surviendra jamais.

2- si la sémantique est importante à tes yeux - et si tous les threads
utilisant cet objet sont correctement synchronisés - la fonction est mal
codée et inutile car nécessairement cet objet est "interrompu" (tous les
threads manipulant cette instance) par le lock dont c'est le but.

3- c'est toujours faux avec l'hypothèse d'une écriture synchronizée car
rien ne prémuni du déroulement suivant (temps croissant de haut en bas)

| thread 1 thread 2
| call thr.isInterrupted()
| mutex.lock()
| mutex.lock()
| register bool state = _interrupt; (suspendu)
| mutex.unlock()
| (libéré)
| _interrupt = !_interrupt;
| ret
| mutex.unlock()
/ @myVariable = register

j'ai mis un "register" pour vous redonnez à moudre des "c'est pas bien" ;-)

cela n'empêchait pas d'alerter l'auteur sur les risques de non
pertinence de sa variable d'état; cela à été dit.


Quelles risques ? Tu ne les as toujours pas précisées.


si tu n'as tjrs pas saisi, je n'y peux plus rien.

Note bien que s'il renvoiait la variable par référence, la
situation serait différente. Mais ce n'était pas le cas.


là j'ai un peu de mal à comprendre - peut être la sémantique, ou la
grammaire.

ce qui était "le cas" était un passage par référence d'une variable
devant contenir "l'état instantané" (un autre concept flou); si ce n'est
pas le cas, voulais-tu imaginer retourner l'adresse de _interrupt ?
dans les 2 cas, cela ne changera rien.

Sylvain.


Avatar
kanze
Sylvain wrote:
kanze wrote on 15/03/2006 08:51:

est-ce propre à ce groupe ou seulement l'habitude de
certains que de faire de la sémantique pour la sémantique ?


C'est le propre de certains d'entre nous de vouloir écrire
un code robuste, en comprenant ce qu'on fait.


on écrit du code là, ici, maintenant, dans ces conditions
gélatineuses sur l'usage de tel adjectif ou la place du'une
virgule ?


Un code correct fait ce qu'il est censé de faire, non ? Alors,
il faut savoir ce qu'il est censé de faire. Sinon, on ne peut
pas savoir s'il est correct.

quelle est "cette" question que soi-même devrait se poser ?


Pour commencer, qu'est-ce qu'on essaie de faire ?


ben en ce moment, à part enculer les mouches, je vois pas ce
que "on" essaie de faire.


Déterminer si un bout de code est correct ? Donc, d'abord,
savoir ce qu'il doit faire.

btw, perso je ne "veux" rien et je n'aurais surement pas
codé une fonction qui fournit une information inutile (par
durée de vie incertaine);


La fonction, telle qu'elle est codée, est très utile. Elle
renvoie la valeur de la variable au moment t où elle est
appelée. À condition qu'il y a une synchronisation semblable
lors de l'écriture, elle remplit bien la fonction qu'elle
est sensée remplir.


incorrect!

1- elle renvoie la valeur qu'à eu la variable "_interrupt" au
moment où elle a été accedé dans la méthode "isInterrupted";


Tout à fait. D'après ce que j'ai compris, c'est aussi ce qu'il
est censé de faire -- au moins, si on peut se fier un peu aux
noms utilisé.

Il est donc correct.

entre cet instant d'évaluation et le moment "t" où la méthode
"isInterrupted" est appellée (tu as bien dit "la fonction ...
est appelée"), il s'écoule un temps indéterminable d'après les
informations fournis - par exemple si le lock est posé par une
autre méthode exécutée par un autre thread que celui réalisant
cet appel à "isInterrupted", le mutex.lock() suspendra cette
exécution, avec dans le pire des cas un deadlock qui
annihilira ton "t" qui ne surviendra jamais.


Et alors ? Je ne vois pas le rapport ? C'est sur que la
possibilité existe que dans un avenir plus ou moins proche, la
valeur de la variable peut changer. Mais je ne vois rien qui me
fait penser que la fonction en question est censée prévoir
l'avenir. Le temps du verbe dans son nom, d'ailleurs, suggère
tout à fait le contraire : « isInterrupted », c-à-d a déjà ét é
interrompu.

Si l'état change dans l'avenir, on le verra dans un prochain
appel à la fonction.

2- si la sémantique est importante à tes yeux - et si tous les
threads utilisant cet objet sont correctement synchronisés -
la fonction est mal codée et inutile car nécessairement cet
objet est "interrompu" (tous les threads manipulant cette
instance) par le lock dont c'est le but.


Est-ce que tu pourrais montrer un cas où le code utilise une
valeur incorrecte ? Si l'écriture est aussi correctement
protégée, je n'en vois pas. Au moment d'appeler la fonction,
j'ai (déjà) été interrompu, ou je ne l'ai pas été. La fonction
renvoie cette information. Ensuite, le code appelant agit en
conséquence.

3- c'est toujours faux avec l'hypothèse d'une écriture
synchronizée car rien ne prémuni du déroulement suivant (temps
croissant de haut en bas)

| thread 1 thread 2
| call thr.isInterrupted()
| mutex.lock()
| mutex.lock()
| register bool state = _interrupt; (suspendu)
| mutex.unlock()
| (libéré)
| _interrupt = !_interrupt;
| ret
| mutex.unlock()
/ @myVariable = register

j'ai mis un "register" pour vous redonnez à moudre des "c'est
pas bien" ;-)


J'avoue ne pas voir de problème ci-dessus. La fonction
isInterrupted a bien renvoyé l'état de _interrupt au moment de
son appel. Tu as l'air d'avoir arrêté le scénario un peu trop
tôt -- qu'est-ce qu'on fait avec quelle variable quand ? Quelle
est la signification de state (que tu initialises, mais dont tu
ne montres pas l'utilisation) ? Qu'est-ce qui ne va pas avec
ce scénario ?

Il faut bien comprendre que l'écriture d'une variable, même
quand on ne detient un lock, ne génère aucun évenemment
asynchrone dans d'autres threads. L'écriture de _interrupt se
fait de façon asynchrone. Vue que c'est un bool, a priori, elle
sert à faire une décision -- cette décision se fait sur l'état
de la variable à un instant t donné. La fonction isInterrupted()
le la variable a un instant t donné, et en renvoie son état.

Où est le problème ?

cela n'empêchait pas d'alerter l'auteur sur les risques de
non pertinence de sa variable d'état; cela à été dit.


Quelles risques ? Tu ne les as toujours pas précisées.


si tu n'as tjrs pas saisi, je n'y peux plus rien.


Je ne suis pas. J'ai du code exactement comme celui posté dans
mes applications. C'est pratiquement la façon standard et
consacrée d'arrêter des threads proprement. (En fait, il en faut
plus, parce qu'il faut aussi débloquer un thread en attente.)

Note bien que s'il renvoiait la variable par référence, la
situation serait différente. Mais ce n'était pas le cas.


là j'ai un peu de mal à comprendre - peut être la sémantique,
ou la grammaire.


Est-ce que tu sais ce que sont des références en C++ ?

ce qui était "le cas" était un passage par référence d'une
variable devant contenir "l'état instantané" (un autre concept
flou); si ce n'est pas le cas, voulais-tu imaginer retourner
l'adresse de _interrupt ? dans les 2 cas, cela ne changera
rien.


Bien sûr que si. Si l'appelant accède directement à la variable,
l'accès n'est pas protégé. Selon Posix, c'est un comportement
indéfini ; dans la pratique, il risque fort de voir la variable
changer en cours de route.

Telle que la fonction est écrit, ça ne peut pas se passer, parce
que la fonction renvoie une copie.

--
James Kanze GABI Software
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
kanze
Sylvain wrote:
kanze wrote on 15/03/2006 08:46:

a priori, il y a autant d'« états réels » qu'il y a de
threads


là j'aurais dit "états potentiellement distincts".


Je trouve qu'« états réels » exprime bien la chose. Chaque
thread a (conceptuellement au moins, et parfois réelement) sa
propre copie de la variable ; les copies ne sont garanties
synchronisées qu'à la suite de certaines opérations. En dehors
de ces synchronisations, la valeur que voit un thread peut
changer pour s'aligner sur celle que voit un autre thread de
façon asynchrone.

Dans la pratique, on utilise des variables partagées de deux
façons : on régarde un état instantané stable, et on travaille
ensuite sur cet état (c'est le cas ici), ou on fait des mises à
jour basées sur l'ancient état. Dans le deuxième cas,
évidemment, il faut maintenir le lock jusqu'à la fin de la mise
à jour. Dans le premier, il suffit de le maintenir le temps de
lire l'état. Tous l'état, évidemment ; le lock sert à assurer
l'atomicité, en plus que la synchronisation. (Ici, il est
probable que la lecture soit atomique en soit, bien qu'aucune
norme ne la garantit.)

et le mot n'a de sens pour un thread donné que dans la
mesure où il accède à la variable.


s'il n'y accède pas, elle n'est pas d'état du tout ?


Elle a un état indéfini.

je ne pensais pas qu'un objet perdait ses membres non
consultés aussi facilement -- si le point est on se tape de
l'état de cette variable là, oui (et merci pour cette grande
clarification).


Tu n'as pas l'air de se rendre compte qu'il y a pas mal de
copies de cet état. Qui ne sont pas toutes synchronisées entre
elles. Quand tu accèdes à la variable, tu vois un état -- pas
forcément celui que verrait un autre thread, évidemment, et si
d'autres threads effecture des modifications en même temps, même
pas forcément un état « possible » selon la logique du
programme.

(Et encore -- si plusieurs threads accèdent sans
synchronisation, on a en général un état indéfini.)


c'est ce que j'ai énoncé il y a 15 posts et que tu refuses de
lire.


Mais ce n'est pas le cas ici. Tout le monde sait qu'il faut
synchroniser les accès à un objet partagé. Le code en question
le fait bien, exactement comme il faut. (Bien, on ne voit pas
l'écriture. Mais a priori, s'il a synchronisé la lecture comme
il l'a fait, il y a tout à parier qu'il en a fait pareil pour
l'écriture.)

--
James Kanze GABI Software
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 3