Ça l'est déjà dans GCC depuis bien longtemps...
Ça l'est déjà dans GCC depuis bien longtemps...
ce n'est pas la definition d'un standard ni de code portable.
Oui mais je pense que loufoque voulait dire que comme c'est déjà sur GCC, ça a de fortes chances d'être suivi par les autres gros compilos, petit à petit.
Mon blog anglais - Mes articles et critiques de livres - FAQ C++0x, avec liste des nouveautés - Conseils sur le C++ - La meilleure FAQ du monde - Avant de créer des classes que vous réutiliserez, regardez si ça n'existe pas déjà - Le site du comité de normalisation du C++
Le guide pour bien débuter en C++ - Cours et tutoriels pour apprendre C++
Il y a de toute manière pleins de problêmes à ce code... Même si c'est celui que j'utilise dans pas mal de cas.
Le principal étant qu'il n'empêche pas une mauvaise programmation. Si le constructeur de l'objet statique entraine l'appel à la fonction, thread-safe ou pas... ca va foirer.
Et puis, vraiment (à part peut être pour gcc) il n'est PAS thread-safe (rien ne force un compilo à le rendre thread-safe). Et je n'ai pas vu de futur standard indiquant qu'il le devienne.
Le code généré par le compilo est ni plus ni moins que:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 if (!is_set) { is_set = true; new(&t)(...); deleteatexit(&t); } return &t;
A noter qu'il serait très facile pour le compilo de remplacer le 'is_set' par un truc genre:
Mais là encore, ce n'est pas thread-safe... Le return &t; pouvant avoir lieu dans un thread qui croit que l'objet est construit alors qu'il est en train d'être construit.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 if (!(InterlockedOr(&bitfield,0x0000001) & 0x0000001) { new(&t)(...); deleteatexit(&t); } return &t;
La solution a base de Critical Section est loin d'être simple ! (http://www.codeguru.com/cpp/misc/mis...le.php/c12897/)
L'overhead par rapport au code initial est tellement rédibitoire que ce *doit* être une option de compilation dans tous les cas.
Pour finir, et contrairement à ce que j'ai vu passer, l'ordre de destruction est parfaitement défini: c'est l'ordre inverse de construction... Et lui pour le coup, est parfaitement thread-safe !![]()
c'est pas une solution a base de section critique, c'est une solution pour initialiser une section critique.
Il y a la possibilité du double locking si on initialise un pinteur
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 A* get() { static A* obj; if(!obj) { DWORD init = 0; if(InterlockedCompareExchange(&init, 1, 0) == 0) //si on aquiere le lock { obj = new A; } while(!obj); // sinon, attente active que le pointeur soit différent de 0 } return obj; }
Dernière modification par screetch ; 13/08/2008 à 14h14.
Voir dans le prochain standard pour savoir ce que doit faire un compilo pour rendre ces choses-là thread-safe.
L'implémentation de GCC n'est pas conforme car elle peut deadlocker dans certains cas.
Heu.... t'as pas du tout lire alors...
Le dernier code montre un exemple pour *rajouter* une partie synchronisée sur l'objet. Si tu remontes au code d'avant tu comprendras...
Heu... on parlait d'une solution à base de :Il y a la possibilité du double locking si on initialise un pinteur
pas de singleton à base de pointeur à coder soi meme !!!
Code : Sélectionner tout - Visualiser dans une fenêtre à part static A obj;
D'ailleurs, dans ton code, il manque un atexit sur une fonction qui va faire le "delete obj" aussi... du coup, le static obj doit être sorti de la fonction pour un résultat *très* loin de la solution initiale:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 { static A obj; return &obj; }![]()
oué oué. ou en etant constructif, mon code + ton code = ca marche.
Je me demandais s'il ne fallait pas redéfinir le constructeur par copie et l'opérateur '=' afin d'éviter de créer plusieurs instances. Peut-être quelque chose m'échappe ?
Partager