 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Aurélien REGAT-BARREL Guest
|
Posted: Thu Feb 03, 2005 3:22 pm Post subject: volatile et template |
|
|
Bonjour,
J'ai une application multi threadée avec le thread principal qui lance un
autre thread en lui donnant en paramètre un smart pointer (c'est pas tout à
fait ça mais presque).
Je voudrais déclarer dans mon thread secondaire le smart pointer comme
volatile, mais ça marche pas (à l'utilisation):
boost::shared_ptr<int> v1( new int );
if ( v1 ) // ok
{
}
volatile boost::shared_ptr<int> v2( new int );
if ( v2 ) // erreur de compilation ici
{
}
comment m'en sortir ?
Merci.
--
Aurélien REGAT-BARREL
|
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Thu Feb 03, 2005 3:28 pm Post subject: Re: volatile et template |
|
|
"Aurélien REGAT-BARREL" <nospam-aregatba (AT) yahoo (DOT) fr.invalid> writes:
| Quote: | J'ai une application multi threadée avec le thread principal qui
lance un autre thread en lui donnant en paramètre un smart pointer
(c'est pas tout à fait ça mais presque). Je voudrais déclarer dans
mon thread secondaire le smart pointer comme volatile, mais ça
marche pas (à l'utilisation):
|
Volatile n'est vraissemblablement pas la solution d'un probleme de
multithread sauf si c'est documente explicitement par ton compilateur
et que tu n'envisages pas qu'un autre soit possible.
| Quote: | boost::shared_ptr<int> v1( new int );
if ( v1 ) // ok
{
}
volatile boost::shared_ptr<int> v2( new int );
if ( v2 ) // erreur de compilation ici
{
}
|
C'est quoi l'erreur?
<boule de cristal>
Si tu fais la meme chose avec const, qu'est que tu as comme erreur?
</boule de cristal>
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
|
|
| Back to top |
|
 |
Aurélien REGAT-BARREL Guest
|
Posted: Thu Feb 03, 2005 4:44 pm Post subject: Re: volatile et template |
|
|
| Quote: | Volatile n'est vraissemblablement pas la solution d'un probleme de
multithread sauf si c'est documente explicitement par ton compilateur
et que tu n'envisages pas qu'un autre soit possible.
|
Hum, je vois pas trop ce que je peux faire, car c'est dans le cadre d'une
lib spéciale : Qt. Les objets Qt dérivent de QObject et c'est Qt qui gère
leur durée de vie (pas via des smart ptr, mais via une relation
parent-enfant : détruire le parent détruit les enfants, plus d'autres
astuces).
Je lance un thread depuis une fenêtre, la fenêtre affiche l'avancement du
thread. Si jamais la fenêtre est fermée avant que le thread ne se termine,
Qt va détruire l'objet fenêtre, et le pointeur donné au thread devient
invalide, et ça plante quand le thread envoie des évènements à la fenêtre
pour signaler la progression de son traitement.
Idéalement il "suffit" de veiller à ne pas détruire la fenêtre avant le
thread. Mais tant qu'à faire, j'aimerais blinder le truc.
La solution que j'ai adopté c'est d'utiliser un pointeur particulier (genre
auto_ptr en fait mais sauce Qt) : sauf que là quand la fenêtre est détruite
le pointeur est mis à NULL automatiquement par Qt. C'est cool ça marche
bien. Reste que ce pointeur est mis à NULL par un autre thread que celui qui
l'utilise, d'où ma volonté de mettre volatile, pour être parfait. Sauf
que...
| Quote: | C'est quoi l'erreur?
|
Alors pour l'exemple donné l'erreur avec VC++ 7.1 c'est:
error C2451: expression conditionnelle de type
'volatile boost::shared_ptr<T>' non conforme
with
[
T=int
]
et j'ai droit aussi à un warning
warning C4127: l'expression conditionnelle est une constante
const ne change rien, const à la place de volatile ça marche.
oublions boost::shared_ptr et nouvel essai avec auto_ptr:
volatile auto_ptr<int> v( new int );
if ( *v == 10 )
{
}
VC++ 7.1 me dit:
error C2678: '*' binaire : aucun opérateur trouvé qui
accepte un opérande de partie gauche de type
'volatile std::auto_ptr<_Ty>' (ou il n'existe pas
de conversion acceptable)
with
[
_Ty=int
]
devcpp me dit:
passing `volatile std::auto_ptr<int>' as `this' argument of
`_Tp& std::auto_ptr<_Tp>::operator*() const [with _Tp = int]'
discards
--
Aurélien REGAT-BARREL
|
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Thu Feb 03, 2005 4:51 pm Post subject: Re: volatile et template |
|
|
"Aurélien REGAT-BARREL" <nospam-aregatba (AT) yahoo (DOT) fr.invalid> writes:
| Quote: | C'est cool ça marche
bien. Reste que ce pointeur est mis à NULL par un autre thread que celui qui
l'utilise, d'où ma volonté de mettre volatile, pour être parfait.
|
Volatile ne regle aucun probleme de visibilite de modification entre
threads. A ma connaissance aucun compilateur n'introduit ce qui est
necessaire automatiquement. Ce qu'il faut depend du systeme et je ne
connais pas Windows.
| Quote: | que...
C'est quoi l'erreur?
Alors pour l'exemple donné l'erreur avec VC++ 7.1 c'est:
error C2451: expression conditionnelle de type
'volatile boost::shared_ptr<T>' non conforme
|
Pas trop clair effectivement. Je ne sais pas si ma supposition est
bonne et j'ai pas le temps d'aller voir boost.
volatile fonctionne comme const, pour appeler des membres sur un objet
const, il faut que ces membres soient const. Pour appeler des membres
sur un objet volatile, il faut que ces membres soient volatiles.
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
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Thu Feb 03, 2005 5:09 pm Post subject: Re: volatile et template |
|
|
On Thu, 3 Feb 2005 17:44:08 +0100, "Aurélien REGAT-BARREL"
<nospam-aregatba (AT) yahoo (DOT) fr.invalid>:
| Quote: | Je lance un thread depuis une fenêtre, la fenêtre affiche l'avancement du
thread. Si jamais la fenêtre est fermée avant que le thread ne se termine,
Qt va détruire l'objet fenêtre, et le pointeur donné au thread devient
invalide,
|
Tu as donc une classe Fenetre et une classe ThreadCalcul. Ce bout de
code devrait fonctionner :
Fenetre::~Fenetre()
{
pointeur_thread_calcul-> NotificationDestructionFenetre();
}
class ThreadCalcul
{
public:
void NotificationDestructionFenetre()
{
HandleCriticalSection::Lock (mutex);
la_fenetre_existe= false;
}
private:
bool la_fenetre_existe;
HandleCriticalSection mutex;
bool LaFenetreExiste()
{
HandleCriticalSection::Lock (mutex);
return la_fenetre_existe;
}
void MiseAJourFenetre()
{
if (LaFenetreExiste())
fenetre-> MiseAJourAffichage();
}
};
http://perso.edulang.com/fclc++/critical_section.h.zip
--
;-)
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Thu Feb 03, 2005 5:11 pm Post subject: Re: volatile et template |
|
|
On 03 Feb 2005 16:28:06 +0100, Jean-Marc Bourguet <jm (AT) bourguet (DOT) org>:
| Quote: | Volatile n'est vraissemblablement pas la solution d'un probleme de
multithread
|
Je dirais même plus : il me semble que volatile est surtout utilisé
sur des systèmes ne gérant pas plusieurs threads, et sert à indiquer
que la variable peut être modifiée par une interruption. En gros, sous
DOS, ça pouvait peut-être servir ; sous Windows 32 bits, guère.
--
;-)
|
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Thu Feb 03, 2005 5:16 pm Post subject: Re: volatile et template |
|
|
On Thu, 03 Feb 2005 18:09:45 +0100, Fabien LE LEZ
<gramster (AT) gramster (DOT) com>:
| Quote: | bool la_fenetre_existe;
HandleCriticalSection mutex;
|
En fait, il vaut mieux enfermer tout ça dans une classe :
template <class T> class VariableAvecMutex
{
public:
void Set (T const& nouvelle_valeur)
{
HandleCriticalSection::Lock (mutex);
valeur= nouvelle_valeur;
}
T Get()
{
HandleCriticalSection::Lock (mutex);
return valeur;
}
private:
HandleCriticalSection mutex;
T valeur;
};
D'où :
class ThreadCalcul
{
public:
void NotificationDestructionFenetre()
{
la_fenetre_existe.Set(false);
}
private:
VariableAvecMutex<bool> la_fenetre_existe;
void MiseAJourFenetre()
{
if (la_fenetre_existe.Get())
fenetre-> MiseAJourAffichage();
}
};
Ne pas oublier de mettre un "la_fenetre_existe.Set(true);" quelque
part...
--
;-)
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Feb 04, 2005 7:56 am Post subject: Re: volatile et template |
|
|
Fabien LE LEZ wrote:
| Quote: | On 03 Feb 2005 16:28:06 +0100, Jean-Marc Bourguet <jm (AT) bourguet (DOT) org>:
Volatile n'est vraissemblablement pas la solution d'un
probleme de multithread
Je dirais même plus : il me semble que volatile est surtout
utilisé sur des systèmes ne gérant pas plusieurs threads, et
sert à indiquer que la variable peut être modifiée par une
interruption. En gros, sous DOS, ça pouvait peut-être servir ;
sous Windows 32 bits, guère.
|
Ça dépend de la définition de « thread ». Les threads actuels ne
sont pas si différents des processus que j'ai connu à l'époque
d'avant memory mapping -- où tous les processus avaient accès à
toutes la mémoire.
En fait, volatile a été conçu surtout pour les entrées/sorties
mappées mémoire. Sur des systèmes simples et primitifs, ils
permettaient des synchronisations entre des interruptions et le
processus principal ou entre deux processus aussi. Mais un PC
moderne, c'est loin d'être un système simple et primitif. (Et en
passant, ce n'est pas réelement le système d'exploitation qui
fait la différence, mais la gestion de la mémoire. Sans cache,
et où une instruction de load ou de store bloque le processeur
jusuqu'à ce qu'elle a fini, volatile a un sens. C-à-d chez
Intel, jusqu'au 80386 à peu près.)
--
James Kanze GABI Software http://www.gabi-soft.fr
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
|
|
| Back to top |
|
 |
Jean-Marc Bourguet Guest
|
Posted: Fri Feb 04, 2005 8:25 am Post subject: Re: volatile et template |
|
|
Fabien LE LEZ <gramster (AT) gramster (DOT) com> writes:
| Quote: | On 03 Feb 2005 16:28:06 +0100, Jean-Marc Bourguet <jm (AT) bourguet (DOT) org>:
Volatile n'est vraissemblablement pas la solution d'un probleme de
multithread
Je dirais même plus : il me semble que volatile est surtout utilisé
sur des systèmes ne gérant pas plusieurs threads, et sert à indiquer
que la variable peut être modifiée par une interruption. En gros,
sous DOS, ça pouvait peut-être servir ; sous Windows 32 bits, guère.
|
Ca peut toujours servir sous Windows ou Unix. D'abord dans les cas
prevus (longjmp), ensuite dans les modules de gestions de
peripheriques ou la "memoire" est quelque chose de bien particulier.
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
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Feb 04, 2005 8:35 am Post subject: Re: volatile et template |
|
|
Fabien LE LEZ wrote:
| Quote: | On Thu, 3 Feb 2005 17:44:08 +0100, "Aurélien REGAT-BARREL"
[email]nospam-aregatba (AT) yahoo (DOT) fr.inva[/email]lid>:
Je lance un thread depuis une fenêtre, la fenêtre affiche
l'avancement du thread. Si jamais la fenêtre est fermée avant
que le thread ne se termine, Qt va détruire l'objet fenêtre,
et le pointeur donné au thread devient invalide,
Tu as donc une classe Fenetre et une classe ThreadCalcul.
|
Laissons tomber les classes jusqu'à ce qu'on a précisé la
dynamique voulue.
| Quote: | Ce bout de code devrait fonctionner :
Fenetre::~Fenetre()
{
pointeur_thread_calcul-> NotificationDestructionFenetre();
}
class ThreadCalcul
{
public:
void NotificationDestructionFenetre()
{
HandleCriticalSection::Lock (mutex);
la_fenetre_existe= false;
}
private:
bool la_fenetre_existe;
HandleCriticalSection mutex;
bool LaFenetreExiste()
{
HandleCriticalSection::Lock (mutex);
return la_fenetre_existe;
}
void MiseAJourFenetre()
{
if (LaFenetreExiste())
|
Changement de thread, invalidation du pointeur, et...
| Quote: | fenetre-> MiseAJourAffichage();
|
Bang !
Ce n'est pas comme ça qu'on gère les threads. La granularité est
trop petite.
Dans son cas, la solution serait sans doute celle imposée par
Qt, que je connais pas. Dans les systèmes de fenêtrage que je
connais, toutes les mises à jours des graphiques se font dans un
thread particulier, qui est aussi celui que gère les
évenemments. Pour mettre à jour un barre d'avancement, par
exemple, on envoie un évenement au thread gestionnaire des
événements, qui s'en occupe. L'alternatif, c'est (en supposant
un MVC) que le thread de calcul fasse la mise à jour du modèle,
puis envoie un événemment au thread d'affichage pour l'informer
qu'il y a eu un changement.
Dans le premier cas, il y a deux solutions :
1. On se sert de l'équivalent d'un boost::weak_ptr dans le
thread de calcul et dans le message. La conversion en
shared_ptr n'a lieu que dans le thread d'affichage, avec les
tests qu'il faut.
Je dis l'équivalent, parce qu'évidemment, les objets gérés
par Qt ne sont pas gérés par boost::shared_ptr. En gros, si
Qt n'offre pas de support direct pour ce genre de chose, il
faudrait dériver de la classe d'affichage, et s'arranger que
le pointeur, et toutes les copies du pointeur, soient
connues de cette classe, pour qu'elle puisse les mettre à
nul dans les pointeurs. Et ce n'est pas évident pour le
faire marcher correctement -- en gros, je dirais que
l'utilisation du pointeur en tant que pointeur ne doit avoir
lieu que dans le thread d'affichage, qui doit aussi être le
seul thread qui pourrait détruire l'objet d'affichage.
Chez Boost, c'est l'ensemble shared_ptr/weak_ptr qui gère la
destruction ; il peuvent donc bien s'arranger pour que la
destruction n'a pas lieu à un moment importun. Ici, c'est Qt
qui le gère, et il faut être certain que Qt ne le fait pas
quand on a déjà extrait le pointeur brut, mais qu'on n'en a
pas encore servi. AMHA, la solution qui s'impose, c'est que
le seul thread qui se sert du pointeur brut, c'est le même
thread que celui qui pourrait éventuellement faire un delete
sur l'objet.
2. À la place d'un pointeur, le thread de calcul a un
identificateur quelconque (entier, string...). Il envoie le
message avec l'identificateur, et c'est le thread
d'affichage qui le cherche dans un map -- s'il n'est pas là,
le thread d'affichage laisse tomber la mise à jour.
Ici aussi, il importe que le delete de l'objet d'affichage
ne peut avoir lieu que dans le thread d'affichage.
Dans le deuxième cas, il faut bien que le thread de calcul ait
accès à l'objet d'affichage. Dans ce cas-là, il faut
impérativement 1) qu'il soit observeur, pour que le pointeur
soit mis à null lors d'un delete, et 2) qu'il detient un lock
aussi longtemps qu'il a une copie du pointeur, et que ce même
lock protège la deletion (c-à-d qu'autant qu'il a le lock, on ne
peut pas deleter). Pour 2), j'aime plutôt l'idée d'un pointeur
intelligent dont le constructeur aquiert le lock, et le dernier
destructeur le libère. On peut se servir de boost::smart_ptr
ici, à condition d'acquérir le lock avant de créer le pointeur,
et que lors de la création initiale, on utilise le constructeur
à deux paramètres, pour lui passer un « deleter » qui libère le
lock (et qui ne delete rien). Évidemment, il faut que le code
qui effectue le delete de l'objet prend le même lock. (Je suis
assez scéptique sur la prise d'un lock dans un destructeur. Mais
à la rigueur, comme première action dans le destructeur de la
classe la plus dérivée. Ce qu'il faut tenir en compte, c'est
qu'entre le moment que la décision a été prise de detruire
l'objet et le moment que le thread d'affichage prend le lock, le
thread de calcul peut interrompre, obtenir un pointeur à l'objet
d'affichage, et s'en servir. Or, si on est déjà dans le
destructeur...)
--
James Kanze GABI Software http://www.gabi-soft.fr
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
|
|
| Back to top |
|
 |
Olivier Azeau Guest
|
Posted: Fri Feb 04, 2005 9:23 am Post subject: Re: volatile et template |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: | Dans son cas, la solution serait sans doute celle imposée par
Qt, que je connais pas. Dans les systèmes de fenêtrage que je
connais, toutes les mises à jours des graphiques se font dans un
thread particulier, qui est aussi celui que gère les
évenemments.
|
La question qui est derriere cela c'est : le systeme de fenetrage
est-il thread-safe ?
Dans le doute, il vaut mieux faire tous les appels a ce systeme dans un
seul et meme thread : meme si la fenetre est toujours présente et que
le thread de calcul y fait un appel, rien ne dit qu'un autre thread de
calcul qui fait, au meme moment, un appel a une autre fenetre ne va pas
causer un probleme au sein du systeme de fenetrage.
Bien souvent (en tt cas dans les applis que je connais), quand on a
besoin d'integrer un composant tiers, systeme de fenetrage ou autre, on
cantonne tous les appels dans un seul thread pour ne pas risquer ce
genre de mésaventure. Je suppose qu'il y a un nom (que je ne connais
pas) a cet idiome.
|
|
| Back to top |
|
 |
Aurélien REGAT-BARREL Guest
|
Posted: Fri Feb 04, 2005 1:09 pm Post subject: Re: volatile et template |
|
|
| Quote: | Dans son cas, la solution serait sans doute celle imposée par
Qt, que je connais pas. Dans les systèmes de fenêtrage que je
connais, toutes les mises à jours des graphiques se font dans un
thread particulier, qui est aussi celui que gère les
évenemments. Pour mettre à jour un barre d'avancement, par
exemple, on envoie un évenement au thread gestionnaire des
événements, qui s'en occupe. L'alternatif, c'est (en supposant
un MVC) que le thread de calcul fasse la mise à jour du modèle,
puis envoie un événemment au thread d'affichage pour l'informer
qu'il y a eu un changement.
|
C'est exactement cela. Le probleme est dans l'envoie de l'évènement. Pour
cela, je dois spécifier la fenêtre destinatrice. Mon probleme : si par la
suite cette fenêtre est détruite, l'envoie d'évènement fait tout crasher
(pointeur null reference). Qt aurait pu être mieux fouttu sur ce point mais
c'est pas le cas. Alors j'ai pris mes précautions, ça ne se produira plus,
mais bon j'aime pas avoir ce genre de sournoiserie qui traine...
Ce qui m'est imposé par Qt, c'est d'utiliser un QObject* comme destinataire
de l'évènement.
Le probleme c'est que si ce QObject* est détruit par la suite, boum
badaboum.
Solution : j'utilise un QGuardedPtr<QObject>, qui a une particularité : être
automatiquement mis à NULL si l'objet pointé est détruit. Ca marche très
bien.
Ma question : le fait que ce QGuardedPtr soit mis à NULL par un autre
thread, je me demande si une optimisation du compilo ne risque pas de lui
faire louper l'info.
C'est un peu comme si on avait ça:
std::shared_ptr<int> ptr( new int );
thread1:
while ( ptr != 0 ) { /* ... */ }
thread2:
/* blablabla */
ptr.reset();
sauf que apparement shared_ptr est thread safe. Mais vous pigez ma question
: le test:
while ( ptr != 0 )
fait dans thread1 ne risque-t-il pas d'être faussé par la modif de thread2
"en parallèle" ?
Bon je réalise que rien n'empêche ptr d'être invalidé après le test... Bref,
je vais devoir faire de la synchronisation.
| Quote: | Dans le premier cas, il y a deux solutions :
1. On se sert de l'équivalent d'un boost::weak_ptr dans le
thread de calcul et dans le message. La conversion en
shared_ptr n'a lieu que dans le thread d'affichage, avec les
tests qu'il faut.
Je dis l'équivalent, parce qu'évidemment, les objets gérés
par Qt ne sont pas gérés par boost::shared_ptr. En gros, si
Qt n'offre pas de support direct pour ce genre de chose, il
faudrait dériver de la classe d'affichage, et s'arranger que
le pointeur, et toutes les copies du pointeur, soient
connues de cette classe, pour qu'elle puisse les mettre à
nul dans les pointeurs.
|
Y'a plus simple dans mon cas : un QGuardedPtr est automatiquement mis à NULL
par Qt une fois l'objet pointé déréférencé.
| Quote: | Et ce n'est pas évident pour le
faire marcher correctement -- en gros, je dirais que
l'utilisation du pointeur en tant que pointeur ne doit avoir
lieu que dans le thread d'affichage, qui doit aussi être le
seul thread qui pourrait détruire l'objet d'affichage.
Chez Boost, c'est l'ensemble shared_ptr/weak_ptr qui gère la
destruction ; il peuvent donc bien s'arranger pour que la
destruction n'a pas lieu à un moment importun. Ici, c'est Qt
qui le gère, et il faut être certain que Qt ne le fait pas
quand on a déjà extrait le pointeur brut, mais qu'on n'en a
pas encore servi. AMHA, la solution qui s'impose, c'est que
le seul thread qui se sert du pointeur brut, c'est le même
thread que celui qui pourrait éventuellement faire un delete
sur l'objet.
|
Y'a pas de delete. Dans mon cas ça s'utilise comme ça:
void MainWnd::OnDoSomething()
{
DoSomethingDialog dialog( this );
dialog.exec();
}
et le exec() lance un thread et affiche une barre de progression qui suit
l'évolution du traitement.
Si le programmeur n'a pas géré la fermeture de DoSomethingDialog de manière
à interrompre le thread / ou attendre qu'il se termine, exec() rend la main,
on sort de OnDoSomething() et le dialog est détruit, mais le thread lui
continue d'envoyer un feedback... sur &dialog, et...
| Quote: | 2. À la place d'un pointeur, le thread de calcul a un
identificateur quelconque (entier, string...). Il envoie le
message avec l'identificateur, et c'est le thread
d'affichage qui le cherche dans un map -- s'il n'est pas là,
le thread d'affichage laisse tomber la mise à jour.
|
Je suis obligé de passer par un QObject* pour envoyer un évènement, car
c'est un mécanisme interne à Qt. Le QObject indiqué reçoit alors l'évènement
via une fonction virtuelle dédiée.
| Quote: | Dans le deuxième cas, il faut bien que le thread de calcul ait
accès à l'objet d'affichage.
|
Ca c'est gênant, ça me fait une dépendance croisée FenetreAffichage <->
ThreadCalcul.
| Quote: | Dans ce cas-là, il faut
impérativement 1) qu'il soit observeur, pour que le pointeur
soit mis à null lors d'un delete, et 2) qu'il detient un lock
aussi longtemps qu'il a une copie du pointeur, et que ce même
lock protège la deletion (c-à-d qu'autant qu'il a le lock, on ne
peut pas deleter).
|
Je ne peux empêcher le delete/destruction, ce serait fâcheux. Dans ce cas ce
n'est plus le thread principal qui controle le thread de calcul, mais le 2°
qui peut bloquer le 1°, et alors la message pump l'est aussi, et donc toute
l'appli aussi, y compris l'envoie d'évènements, plus rien ne fonctionne...
Je préfère l'autre sens : le thread d'affichage tue le process avant de
fermer le dialog, ou plus proprement lui dit de s'arrêter (ce qui est
logique même si je n'avais pas ce probleme).
| Quote: | Pour 2), j'aime plutôt l'idée d'un pointeur
intelligent dont le constructeur aquiert le lock, et le dernier
destructeur le libère. On peut se servir de boost::smart_ptr
ici, à condition d'acquérir le lock avant de créer le pointeur,
et que lors de la création initiale, on utilise le constructeur
à deux paramètres, pour lui passer un « deleter » qui libère le
lock (et qui ne delete rien). Évidemment, il faut que le code
qui effectue le delete de l'objet prend le même lock. (Je suis
assez scéptique sur la prise d'un lock dans un destructeur. Mais
à la rigueur, comme première action dans le destructeur de la
classe la plus dérivée. Ce qu'il faut tenir en compte, c'est
qu'entre le moment que la décision a été prise de detruire
l'objet et le moment que le thread d'affichage prend le lock, le
thread de calcul peut interrompre, obtenir un pointeur à l'objet
d'affichage, et s'en servir. Or, si on est déjà dans le
destructeur...)
|
Oui je comprend. Mais je vais faire plus simple. Au lieu de passer un
QObject* simple à mon thread de calcul (pour envoyer le feedback), je vais
lui donner une structure "concurrent access safe" qui permet de savoir si
l'arrêt du traitement a été demandé. Si c'est le cas il n'envoie plus
d'évènements et se termine (mais je garde mon QGuardedPtr pour une double
sécurité, et parce que je suis content de lui avoir touvé une utilité .
Merci pour tes idées.
--
Aurélien REGAT-BARREL
|
|
| Back to top |
|
 |
Aurélien REGAT-BARREL Guest
|
Posted: Fri Feb 04, 2005 1:12 pm Post subject: Re: volatile et template |
|
|
| Quote: | Volatile ne regle aucun probleme de visibilite de modification entre
threads. A ma connaissance aucun compilateur n'introduit ce qui est
necessaire automatiquement. Ce qu'il faut depend du systeme et je ne
connais pas Windows.
|
A quoi sert volatile alors ?
Sinon c'est pas spécifique Windows. Je développe sous Windows certes, mais
Qt est portable (Win/Unix/Mac) et je souhaite conserver cette option, on
sait jamais. Y'a ce qu'il faut pour la synchro classique. Je vais m'en
servir pour demander au thread de s'arrêter.
--
Aurélien REGAT-BARREL
|
|
| Back to top |
|
 |
Aurélien REGAT-BARREL Guest
|
Posted: Fri Feb 04, 2005 1:26 pm Post subject: Re: volatile et template |
|
|
| Quote: | fenetre-> MiseAJourAffichage();
|
Pas possible. L'appel direct comme n'est pas applicable dans mon cas, car
MiseAJour() crée un timer (pour simuler l'avancement) et alors c'est le
thread de calcul qui crée le timer, et comme ce dernier est associé à une
fenêtre créée par un autre thread, ça marche pas, du moins sous Windows
(limitation de SetTimer ou de Qt, je sais pas).
Donc je dois envoyer (en asynchrone) un évènement que la fenêtre cible va
recevoir et c'est elle qui va faire sa popotte.
Merci mais je vais utiliser un bon vieux Mutex de chez Qt, car je souhaite
rester le plus portable possible.
--
Aurélien REGAT-BARREL
|
|
| Back to top |
|
 |
Aurélien REGAT-BARREL Guest
|
Posted: Fri Feb 04, 2005 1:40 pm Post subject: Re: volatile et template |
|
|
| Quote: | La question qui est derriere cela c'est : le systeme de fenetrage
est-il thread-safe ?
|
Je doute qu'il y ait un framework dont chaque classe / fonction est thread
safe, surtout en ce qui concerne les classes de fenêtrage. Dans le cas de
Qt, les classes de synchro le sont (Mutex, Semaphore, ...), plus quelques
fonctions de communication par évènements et la classe de QThreadStorage.
Sinon la classe de base QObject est réentrante, mais à part ça pas grand
chose. Ce qui est un argument supplémentaire contre la proposition de Fabien
qui travaille directement la fenêtre de contrôle depuis le thread de calcul.
| Quote: | Dans le doute, il vaut mieux faire tous les appels a ce systeme dans un
seul et meme thread : meme si la fenetre est toujours présente et que
le thread de calcul y fait un appel, rien ne dit qu'un autre thread de
calcul qui fait, au meme moment, un appel a une autre fenetre ne va pas
causer un probleme au sein du systeme de fenetrage.
|
En Qt, pour ce que j'en sais, l'appel depuis un thread d'une fonction membre
d'un objet (style Fenêtre...) qui a été créé par un autre thread est
considéré comme imprévisible, à proscrire donc (sauf cas particuliers
classes de synchro etc...).
--
Aurélien REGAT-BARREL
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|