Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2462 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  EnterCriticalSection

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

EnterCriticalSection

n°1912155
Glock 17Pr​o
Posté le 06-08-2009 à 08:25:39  profilanswer
 

salut,

 

vous l'utilisez de quelle façon sur un objet, qui à un mutex déclaré en membre donnée :
1)
OBjet instance;
instance.AcquerirMutex()
istance.functionCritique()
insance.relaese

 

2)
OBjet::functionCritique()
{
AcuerirMutex()
//code
Release()
}

 


ça revient au même ?

 

Merci


Message édité par Glock 17Pro le 06-08-2009 à 08:27:54
mood
Publicité
Posté le 06-08-2009 à 08:25:39  profilanswer
 

n°1912156
Joel F
Real men use unique_ptr
Posté le 06-08-2009 à 08:35:36  profilanswer
 

je préfére 2/

n°1912160
budlite
Fresh
Posté le 06-08-2009 à 08:53:30  profilanswer
 

Ben si ta fonction critique est utilisée exclusivement dans des sections critiques, je pense qu'il est preferable de mettre le acquire/release dans la methode, donc je dirais 2.


---------------
Fresh
n°1912168
Glock 17Pr​o
Posté le 06-08-2009 à 09:12:42  profilanswer
 

d'acc merci

n°1915371
Glock 17Pr​o
Posté le 15-08-2009 à 12:28:07  profilanswer
 

et imaginons que la foncion retourne une référence sur une donné:
 
 
Object2* OBjet::functionCritique()
{
AcuerirMutex()
vector<Object2*>::iterator it_res=find(...)
Release()
return ptrObject2;
}
 
Là il vaut  mieux locker/unlocker à l'extérieur de la fonction ?

n°1915374
Joel F
Real men use unique_ptr
Posté le 15-08-2009 à 12:54:45  profilanswer
 

la c'est un pointeur :€
sinon je vois pas la difference que ca fait :o

n°1915380
Glock 17Pr​o
Posté le 15-08-2009 à 13:28:23  profilanswer
 

La différence pour moi est la suivante :

 

Si juste aprés l'appel à Release() (et avant le return), le système switch sur un autre thread, et qu'une fonction Delete() soit appelée sur ptrObject2, in finé en retour de la fonction functionCritique() on se retrouve avec un ptrObject2 qui pointe sur une zone mémoire désaoullé, alors que si on lock en dehors de la fonction, on peut faire l'opération désirée sur le pointeur ptrObject2 retourné et relâcher le verrou qu'à partir de ce moment là. c'est très classique comme problème j'imagine...


Message édité par Glock 17Pro le 15-08-2009 à 13:41:29
n°1915448
Joel F
Real men use unique_ptr
Posté le 15-08-2009 à 20:01:45  profilanswer
 

t'as aussi le droit d'utiliser pas des pointeurs :o

n°1915496
Glock 17Pr​o
Posté le 16-08-2009 à 13:20:04  profilanswer
 

ué mais c'est chaud niveau overhead que ça implique

n°1915502
Joel F
Real men use unique_ptr
Posté le 16-08-2009 à 14:45:05  profilanswer
 

o_O ah bon ?
je vois pas en quoi

mood
Publicité
Posté le 16-08-2009 à 14:45:05  profilanswer
 

n°1915512
Glock 17Pr​o
Posté le 16-08-2009 à 15:54:36  profilanswer
 

en faite il faut savoir que les vector de la stl créer une copie des objets stockées, si j'utilise des pointeurs la copie ne représentera que 4 octets , voilà pourquoi le fait de ne pas passer par des pointeurs induit un overhead

n°1915514
Joel F
Real men use unique_ptr
Posté le 16-08-2009 à 17:04:04  profilanswer
 
n°1915518
jesus_chri​st
votre nouveau dieu
Posté le 16-08-2009 à 18:05:45  profilanswer
 

J'ajouterai qu'utiliser de la RAII pour le mutex peut être mieux, comme boost::mutex. Là si find() lance une exception, t'es mal, même si en l'occurence ça doit être une no-throw.
 
Joel : je crois que glock à qd même raison là. Quelquesoit le niveau d'optim du compilo, et même s'il peut éviter la copie dans vector::push_back et vector::insert, le vecteur est un container qui peut copier son contenu en s'agrandissant.
Utiliser un std::deque serait déjà mieux pour éviter les copies.
De plus, std::vector doit stocker l'information à un endrait précis de la mémoire (derrière le dernier élément en gros), alors que l'objet passé en argument de vector::push_back/vector::insert ne peut pas être à cet endroit, même si c'est une rvalue. Donc la copie est inévitable.
 
Ton article, interressant au passage, parle de la copy-elision autour d'un appel de fonction, pour dir que
T func( T t );,
T func( const T& t ); et
void func( const T& t_in, T& t_out );
 
avec un bon compilo, c'est à peut près pareil. En regardant l'implémentation de std::vector, aucun cas on ne peut éviter au moins copie, en pratique surement plusieurs. Avec std::deque, il n'y en a qu'une.
 
Comme je suis chaud, je tente un récapitulatif des copies, pour un container de taille N.
Je confonds volontairement copie et copy-construction.
 
std::vector< T > : N copies au mieux, N²/2 au pire
std::deque< T > : exactement N copies
std::vector< T* > : 0 copies, mais pas RAII
std::deque< T* > : 0 copies, mais pas RAII
std::deque< boost::optional< T > > : entre 0 et N copies selon T
 
pas RAII avec les pointeurs car le destructeur de std::vector ne libère pas la mémoire pointée. Il existe dans boost il me semble un vector< T* > qui libère la mémoire pointée pour retrouver du RAII. Ou alors utiliser std::vector< boost::shared_ptr< T > > mais c'est lourd.
std::deque< boost::optional< T > > permet d'éviter le niveau d'indirection mais la syntaxe de construction du nouvel objet est complexe pour éviter la copie. Si T ne peut être raisonablement contruit que par copie (une structure POD par exemple) il n'y a pas de gain.
 
De toute façon si tu doit utiliser des pointeurs vers les éléments de ton vecteur à différents endroit, vector n'est pas le bon choix, prends deque, qui lui ne déplace pas ses éléments.

n°1915519
Joel F
Real men use unique_ptr
Posté le 16-08-2009 à 18:20:05  profilanswer
 

test avant de dire tu seras surpris ;)

 

Je veux dire regarde le code de glock :

 
Code :
  1. Object2* OBjet::functionCritique()
  2. {
  3. AcuerirMutex()
  4. vector<Object2*>::iterator it_res=find(...)
  5. Release()
  6. return ptrObject2;
  7. }
 

Tu mets

 
Code :
  1. Object2 OBjet::functionCritique()
  2. {
  3. AcuerirMutex()
  4. vector<Object2*>::iterator it_res=find(...)
  5. Release()
  6. return *ptrObject2;
  7. }
 

et hop tu copy-ellide. Y  a pas d'histoire de vecteur qui grandit. Ilr envoit une instance d'un element


Message édité par Joel F le 16-08-2009 à 18:24:21
n°1915621
Glock 17Pr​o
Posté le 17-08-2009 à 10:09:50  profilanswer
 

Vous me conseillerez quoi comme bon livre concernant le multi-threading ?

n°1915953
Evadream -​jbd-
Posté le 17-08-2009 à 19:52:30  profilanswer
 

J'aime bien http://www.manning.com/williams/
 
C'est spécifique C++1x, mais ça s'adapte très facilement à Boost.Thread. (C'est souvent uniquement une histoire d'include et de namespace).


Message édité par Evadream -jbd- le 17-08-2009 à 19:52:37
n°1915958
Glock 17Pr​o
Posté le 17-08-2009 à 20:01:03  profilanswer
 

je prends note, si d'autres personnes peuvent confirmer ajouter infirmer etc je suis preneur

n°1915992
Glock 17Pr​o
Posté le 17-08-2009 à 22:32:41  profilanswer
 


oui mais là il parle pas de non différence avec les compilo moderne entre vector<string> et vector<string*>  
ça parle de vector<string> f() et vector<string>& f()
 
ça me semble différent...

n°1915993
Glock 17Pr​o
Posté le 17-08-2009 à 22:36:44  profilanswer
 

ou alors si c'est la même chose je suis pas convaincu que mes objets copiés soient des R-value....

n°1915994
jesus_chri​st
votre nouveau dieu
Posté le 17-08-2009 à 22:37:33  profilanswer
 

ah ça y est, ça s'apelle c++1x maintenant...
 
@Joel : je suis d'accord avec toi sur ton bout de code, pour functionCritique(). Ce que je dit c'est que d'après son implémentation standard, vector<Object2> impose toujours au moins N copies à sa création. Ensuite en accès (comme ici) ça peut se copy-ellide en effet.
 
Je maintiens que vector<Object2>::push_back fait "normalement" au moins une copie, sauf si son argument est une r-value où là il y a peut-être ellision. De plus à tout ajout (push_back/insert) std::vector peut recopier ses élements, et là il n'y a pas d'élisions qui vaille, cf le standard.
 
Perso je reste méfiant quand au fait de choisir un coding-style qui suppose que le compilateur fera un super-boulot. Je préfère éviter à la main un maximum de copies, avec const& et plus tard const&&. Autrement dit, je n'utilise pas une implémentation qui copie sauf si le compilo arrive à ellide, je préfère une implémentation qui ne copie pas parce que c'est écrit comme ça. Je changerai d'avis qd l'ellision sera imposée par le standard.
 
std::string toto();
 
const std::string x = toto(); // ok si ellision
const std::string& y = toto(); // toujours ok
 
edit : && et non pas const&& qui n'est pas + utile que le const& classique.

Message cité 1 fois
Message édité par jesus_christ le 17-08-2009 à 22:40:57
n°1915995
jesus_chri​st
votre nouveau dieu
Posté le 17-08-2009 à 22:39:57  profilanswer
 

grillaid par Glock...
donc je rejoins Glock : l'article parle ellision, donc autour de petits bouts de code bien inlinable et eliidable, mais la représentation vector<T> et vector<T*> reste fondamentalement différente. Au niveau du RAII, et au niveau des copies, même si qlq unes peuvent être ellidées.

n°1916059
Joel F
Real men use unique_ptr
Posté le 18-08-2009 à 08:31:58  profilanswer
 

jesus_christ a écrit :


@Joel : je suis d'accord avec toi sur ton bout de code, pour functionCritique(). Ce que je dit c'est que d'après son implémentation standard, vector<Object2> impose toujours au moins N copies à sa création. Ensuite en accès (comme ici) ça peut se copy-ellide en effet.


coolos quoi, je vois 0 push_back dans ce code. Je me doutes bien que push_back copie :E La il renvoit une valeur, c'est typquement un cas d'ellision possible.
Je vois pas pourquoi tu t'acharne su ton push_back, c'est clariement pas l'objet du code INITIAL posté apr Glock.

 

Quant au coding style, j'y peut rien si t'es coincé en gcc 2.95.2 ou en VC6 :o
L'exemple posté par dave dans les commentaires marche avec ellission sur gcc 4.1+ et MSVC 2005+ Apres moi ... je dis ça je dit rien.


Message édité par Joel F le 18-08-2009 à 08:32:54
n°1917501
jesus_chri​st
votre nouveau dieu
Posté le 21-08-2009 à 22:05:49  profilanswer
 

pour remplir son vecteur il doit bien faire des push_back/insert, donc la sémantique par copie compte aussi, mais c'est vrai que ce n'est pas le sujet.
 
J'ai une question au passage sur la durée de vie des rvalues. Si j'écris ça :
 
std::string f();
std::string x = f().c_str();
 
le c_str() est volontaire. f renvoie une string par valeur, en rvalue, et cette dernière est convertie en const char* pour être copiée à travers ce const char* dans x.
Mais question est : la rvalue de f() ne serait-elle pas détruite juste après l'appel de c_str() mais juste avant la copie, et ne copierait donc t-on pas depuis un char* invalide ?
Quand est détruite la rvalue ? juste après le ;, après la première évaluation (ici par c_str()) ou à la fin de scope ?
 
et cette syntaxe :
const std::string& x = f();
force-t-elle le compilo à laisser la rvalue "vivante" jusqu'à la fin du scope ou est-ce juste un moyen de garder une référence sur un object qui serait de toute façon resté sur la pile.
 
je fais assez souvent des appels cascadés sur des rvalue comme :
 
MonObject().GetAttribute().GetName().c_str()
 
et je ne sais pas trop si ici par exemple MonObject() est encore vivant quand c_str() est appelé.

n°1917741
Joel F
Real men use unique_ptr
Posté le 24-08-2009 à 09:38:38  profilanswer
 

jesus_christ a écrit :


J'ai une question au passage sur la durée de vie des rvalues. Si j'écris ça :
 
std::string f();
std::string x = f().c_str();
 
le c_str() est volontaire. f renvoie une string par valeur, en rvalue, et cette dernière est convertie en const char* pour être copiée à travers ce const char* dans x.
Mais question est : la rvalue de f() ne serait-elle pas détruite juste après l'appel de c_str() mais juste avant la copie, et ne copierait donc t-on pas depuis un char* invalide ?
Quand est détruite la rvalue ? juste après le ;, après la première évaluation (ici par c_str()) ou à la fin de scope ?


EN c++1x, le constrcuteur de string par char**&& doit betement faire un swap, ce qui est suffisant.
 

jesus_christ a écrit :


et cette syntaxe :
const std::string& x = f();
force-t-elle le compilo à laisser la rvalue "vivante" jusqu'à la fin du scope ou est-ce juste un moyen de garder une référence sur un object qui serait de toute façon resté sur la pile.


http://herbsutter.spaces.live.com/ [...] !378.entry
 

jesus_christ a écrit :


je fais assez souvent des appels cascadés sur des rvalue comme :
 
MonObject().GetAttribute().GetName().c_str()
 
et je ne sais pas trop si ici par exemple MonObject() est encore vivant quand c_str() est appelé.


c_str() renvoit du caca des que la string qu'il reference est detruite, on ne doit sans servir que pr une utilsiation par const char* ou une recopie.

n°1918676
Glock 17Pr​o
Posté le 26-08-2009 à 21:57:52  profilanswer
 

Ué sympa ton article


---------------
.
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  EnterCriticalSection

 

Sujets relatifs
Plus de sujets relatifs à : EnterCriticalSection


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)