IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

utiliser shared_from_this dans le destructeur


Sujet :

Boost C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 79
    Par défaut utiliser shared_from_this dans le destructeur
    Bonjour,

    J'ai fait un petit moteur de physique du point. Dans ce moteur, il y a l'objet moteur, les objets points et les objets interactions (force de friction, de gravité, etc)

    Les points sont dans des shared_ptr.

    Pour un point donné, toutes les interactions qui l'utilise ainsi que le moteur ont un weak_ptr vers celui ci. Lorsque le point est supprimé, il faut donc prévenir le moteur et les interactions de ne plus l'utiliser.

    Pour cela, j'ai fait le système suivant:
    - un point a la liste de l'ensemble de ceux qui ont un weak_ptr vers lui.
    - ceux qui utilisent un Point ont une méthode RemovePoint( weak_ptr<Point> iPoint ), qui signifie qu'ils doivent arreter d'utiliser iPoint.
    - Lors de l'appel à son destructeur, un point appelle sur chaque objet de sa liste d'utilisateur la méthode RemovePoint, avec shared_from_this() en tant que paramètre, pour leur dire d'arreter de l'utiliser.

    Malheureusement, cela ne marche pas car shared_from_this plante à l'éxécution lorsqu'il est appelé dans le destructeur. On dirait qu'on ne peut pas utiliser shared_from_this dans le destructeur.

    Savez vous si c'est vrai?
    Connaissez vous une meilleure méthode pour prévenir les objets ayant un weak_ptr que l'objet pointé est détruit?

    Merci d'avance!!!

  2. #2
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par nonozor Voir le message
    Bonjour,
    Malheureusement, cela ne marche pas car shared_from_this plante à l'éxécution lorsqu'il est appelé dans le destructeur. On dirait qu'on ne peut pas utiliser shared_from_this dans le destructeur.
    Ca semble assez logique en effet. Renvoyer un shared_ptr depuis l'instance courante revient à partager la responsabilité sur une ressource qui est en cours de destruction. Eh oui, un destructeur ne doit jamais échouer (i.e ne lance pas d'exception, etc...), et là tu veux donner un shared_ptr sur this dans un destructeur. Non, non, non.

    J'ai déjà géré ce genre de truc avec:
    - Un test systématique des weak_ptr et suppression si le test échoue. La base de l'utilisation du weak_ptr, c'est d'utiliser lock() pour s'assurer que le pointeur est valide. S'il est valide, ok. Sinon, on détruit ce qu'il faut (std::map ou autre qui contiendrait d'autres weak_ptr).
    - Un avertissement de destruction de la ressource à base de boost::signals2. C'est surement la solution la plus propre. Surtout que le destructeur de boost::shared_ptr peut être redéfini, donc tout ça pourrait être fait automatiquement.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 79
    Par défaut
    Merci pour ta réponse!

    Citation Envoyé par poukill Voir le message
    - Un test systématique des weak_ptr et suppression si le test échoue. La base de l'utilisation du weak_ptr, c'est d'utiliser lock() pour s'assurer que le pointeur est valide. S'il est valide, ok. Sinon, on détruit ce qu'il faut (std::map ou autre qui contiendrait d'autres weak_ptr).
    Oui, j'ai pensé à ça. Mais faire des tests à chaque fois que j'utilise un pointeur me fait mal au coeur quand je me dit que l'utilisation pourrait être "vas y, tu n'as pas besoin de vérifier, ce pointeur sera toujours valide jusqu'à ce qu'on t'informe du contraire".


    Citation Envoyé par poukill Voir le message
    - Un avertissement de destruction de la ressource à base de boost::signals2. C'est surement la solution la plus propre. Surtout que le destructeur de boost::shared_ptr peut être redéfini, donc tout ça pourrait être fait automatiquement.
    Je ne connais pas boost::signals2. Tu en ferais quelle utilisation?

  4. #4
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par nonozor Voir le message
    Je ne connais pas boost::signals2.
    Pour info, boost.Signals est une implémentation C++ du pattern Observateur. Il vise à découpler la communication observeur/observé. Boost.Signals2 est une version thread-safe de boost.signals. C'est mieux.
    Tuto ici : http://www.boost.org/doc/libs/1_43_0.../tutorial.html

    Tu en ferais quelle utilisation?
    Je connecterai les "fonctions" qui doivent être mises au courant de la destruction de l'objet. Après la lecture du tutorial, tu devrais avoir quelques idées. Si ce n'est pas le cas, j'essaierai demain d'écrire un petit bout de code pour illustrer mes propos !!!

    Sur ce, bonne nuit !

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 79
    Par défaut
    Bonjour,

    De ce que j'ai compris à Boost.Signals2, les Interactions pourraient avoir des fonctions qui seraient connectées aux boost::signals2::signal des Points qu'elles utilisent. A l'appel du destructeur d'un Point, le signal de ce Point appelerait les fonctions des Interactions qui utilisent ce Point pour les prévenir de ne plus l'utiliser.

    Cependant, j'ai une interaction Collision qui utilise plusieurs points. Quand un Point est détruit, comment est ce que son signal pourra préciser à Collision le Point à enlever de sa liste de Points? Je voulait utiliser le pointeur du Point, qui est un identifiant unique à chaque Point, comme indication mais j'ai eu le problème du shared_from_this() qui ne marche plus dans le destructeur.

    Pourrais tu m'aider sur ce point, stp?
    Merci!

  6. #6
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    J'ai fait un premier exemple en utilisant uniquement les fonctionnalités du weak_ptr. Après tout, si tu stockes un weak_ptr, c'est que tu n'en prends pas la responsabilité. Le code de "test" de la validité n'est pas lourd, mais demande effectivement de le faire systématiquement.
    L'exemple montre la destruction à la volée d'objets qui n'existent plus !

    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
    #include <iostream>
    #include <list>
    #include <limits> 
     
     
    #include <boost/signals2.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/weak_ptr.hpp>
     
     
    class Point
    {
    public:
    	friend std::ostream& operator<< (std::ostream& os, const Point& p);
     
    	Point(int x, int y)
    		:m_x(x), m_y(y)
    	{}
     
    private:
    	int m_x;
    	int m_y;
    };
     
    std::ostream& operator<< (std::ostream& os, const Point& p)
    {
    	return os << "[" << p.m_x << "," << p.m_y << "]";
    }
     
    typedef boost::shared_ptr<Point> point_ptr;
    typedef boost::weak_ptr<Point> point_wptr;
     
     
    class Interaction
    {
    public:
    	Interaction() {}
     
    	void AddPoint(point_ptr p)
    	{
    		m_points.push_back(p);
    	}
     
    	void ApplyToAll()
    	{
    		std::cout << "---List of Points----" << std::endl;
    		for (std::list<point_wptr>::iterator iter = m_points.begin(); iter != m_points.end();)
    		{
    			point_ptr p = iter->lock();
    			if (p)
    			{
    				std::cout << *p << std::endl;
    				++iter;
    			}
    			else
    			{
    				iter = m_points.erase(iter);
    			}
    		}
    		std::cout << std::endl;
    	}
     
    private:
    	std::list<point_wptr> m_points;
    };
     
    int main()
    {
    	Interaction inter;
    	point_ptr p1 (new Point(2, 3));
    	inter.AddPoint(p1);
    	inter.ApplyToAll();
    	{
    		point_ptr p2 (new Point(4,5));
    		inter.AddPoint(p2);
    		inter.ApplyToAll();
    	}
    	inter.ApplyToAll();
     
    	std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
     
    	return 0;
    }
    Je vais me pencher sur le cas avec boost.Signals maintenant !

  7. #7
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Bon, j'ai regardé avec boost.Shared_ptr et boost.Signals2 et pour l'instant j'ai rien trouvé de satisfaisant. C'est très intrusif, pénalisant en performance et c'est bien lourd aussi.

    La première solution reste quand même relativement élégante...

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 79
    Par défaut
    Merci Poukill! La première solution doit bien marcher.

    Il y a aussi la solution du RemovePoint( weak_ptr<Point> iPoint ) dont je parlais au début. Cette méthode existe pour tous ceux qui utilise un Point et demande de ne plus utiliser iPoint. Lorsqu'un Point est détruit, il appelle RemovePoint ( weak_ptr<Point> iPoint ) de tous les objets qui l'utilisent, en se mettant en tant que paramètre de la fonction, en faisant RemovePoint( shared_from_this() ). Elle est assez similaire, je pense, à la méthode qui utilise les boost::signal2.

    Cependant, cette méthode se heurte au problème que shared_from_this ne marche pas dans le destructeur.

    Est ce que quelqu'un a une idée d'alternative?
    Merci!

  9. #9
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par nonozor Voir le message
    Merci Poukill! La première solution doit bien marcher.
    Elle marche !
    J'avais utilisé cette méthode personnellement dans un projet réseau.

    Il y a aussi la solution du RemovePoint( weak_ptr<Point> iPoint ) dont je parlais au début.
    C'est grosso modo ce que j'avais essayé hier, mais sans succès.
    Il y a éventuellement la solution d'associer un Identifiant Unique à chaque entité dont tu souhaites gérer le cycle de vie. C'est pas forcément débile pour un moteur, mais peut-être overkill.

    Là je donne ma langue au chat !

Discussions similaires

  1. Réponses: 10
    Dernier message: 14/06/2010, 10h58
  2. Comment utiliser Opengl dans Visual Basic 6
    Par fun31 dans le forum OpenGL
    Réponses: 1
    Dernier message: 03/12/2004, 10h17
  3. [CR] Peut-on utiliser CR dans un programme en C
    Par mboucetta dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 11/10/2004, 10h56
  4. Réponses: 1
    Dernier message: 28/04/2004, 19h18
  5. [CR][VB6] comment utiliser CR dans VB ?
    Par kouassi_denis dans le forum SDK
    Réponses: 2
    Dernier message: 26/01/2004, 16h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo