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

C++ Discussion :

Memory Managment, Smart Ptr et exemple concret :


Sujet :

C++

  1. #1
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut Memory Managment, Smart Ptr et exemple concret :
    Bonjour à tous .

    Tout d'abbord une question d'ordre général, je cherche à gérer les problème de mémoire qui peuvent survenir dans une application, pour cela j'ai vu globalement 2 méthodes :

    - surcharge des new / delete [ j'ai du mal a totu assimilé à ce niveau ... et j'ai du mal à mettre vraiment le nez dedans ]
    - création d'un classe mère avec un conteneur static de tou les objets, le tout agrémenter de smart ptr .

    Je me demande si je ne peux pas m'en sortir, uniquement a l'aide de smart ptr , de cette facons, plus de problème avec les new/delete, et le reste du code ne doit normalment pas posé de problème, la destruction des objet étant automatique ... je me trompe ?

    J'attend vos conseils

    Sinon, je commence à peine à manipuler les smart ptr , et j'essaie de me faire la main dessus, et je me heurte à un petit problème : je veux implémenter une version simple ( dans le simple but de tester ) d'une manager de texture .

    Celui-ci possède une simple fonction Get(), qui va :
    - charge la texture associé à l'ID passé en argument si ce n'est déja fait
    - retourner un pointeur vers la texture quoi qu'il arrive

    Ca marche, pas de problème, et mes texture sont détruite automatiquement quand on TextureManager est détruit .

    Le problème est qu'il manque une foncitonalité que je n'arrive pas à coder :

    Quand tout les objets utilisant une texture donné sont détruit, la texture doit être détruite , hors dans mon code ce n'est pas possible, car je stocke mes texture dans une map qui associe un entier, avec un smart ptr vers la texture, donc quoi qu'il arrive , jusqu'à la mort de mon manager, il restera un smart ptr qui pointera vers chaqu'une de mes textures :

    voila le code minimal qui reproduit ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class CItem
    {
    public :
    	boost::shared_ptr<CTexture> T ;
    };
    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
    class CTexture
    {
    public :
    	CTexture(int ID_t)
    	{
    		ID = ID_t ;
    		std::cout << "Texture " << ID << " is created" << std::endl ;
    	}
    	~CTexture()
    	{
    		std::cout << "Texture " << ID << " is destroyed" << std::endl ;
    	}
    private :
    	int ID ;
    };
    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
    #include <vector>
    #include <map>
     
    class CTextureManager
    {
    public:
    	boost::shared_ptr<CTexture> Get(int ID)
    	{
    		if ( Map_Texture.find(ID) == Map_Texture.end() )
    		{
    			Map_Texture[ID] = boost::shared_ptr<CTexture>( new CTexture(ID)) ;
    		}
    		return Map_Texture[ID] ;
    	}
    private :
    	std::map <int, boost::shared_ptr<CTexture> > Map_Texture ;
    };

    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
    int main(int argc, char *argv[])
    {
    	SDL_Init(0);
    	CTextureManager M ;
     
    	CItem I;
    	{
    	CItem I1,I2 ;
     
    	I.T = M.Get(0);
    	I1.T = M.Get(1);
    	I2.T = M.Get(1) ;
    	}
    	std::cout << " ------------------------ " << std::endl ;
     
     
    	SDL_Quit();
     
    	return 0;
    }
    Le fichier output :

    Texture 0 is created
    Texture 1 is created
    ------------------------
    Texture 1 is destroyed
    Texture 0 is destroyed
    J'aimerai que la texture 1 soit détruite juste après l'acolade fermente ( donc aprés le "----" dans l'output ) .

    Merci .

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Il suffit que ton gestionnaire de texture n'incrémente pas le compteur de référence des textures qu'il stocke. Ca doit pouvoir se faire avec boost, mais je ne connais pas les détails.

    Mais en général on veut garder ce comportement, pour éviter qu'une texture inutilisée ne soit déchargée immédiatement. Disons que c'est encore mieux si c'est toi qui gère la destruction des textures, plutôt que les pointeurs intelligents.

  3. #3
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Effectivement, il y a un truc, je l'indique dans mon tuto sur Boost.SmaprtPtr, c'est la classe weak_ptr<> qui n'incrémente pas le compteur de références. Mais attention, comme le dit Laurent, dès qu'une référence est détruite, la mémoire est désallouée, ce qui fait que le weak_ptr<> est invalidé et donc ne peut plus se transformer en shared_ptr<>, il faut donc détecter ce cas, mais je ne sais pas quelle est la réponse dans le cas où on vient de créer la bête -> quand tu crées ton weak_ptr<>, retourne directement un shared_ptr<> grâce à la fonction lock(), et la condition sera aussi un test de validité du pointeur trouvé.

  4. #4
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    Mais en général on veut garder ce comportement, pour éviter qu'une texture inutilisée ne soit déchargée immédiatement. Disons que c'est encore mieux si c'est toi qui gère la destruction des textures, plutôt que les pointeurs intelligents.
    Je pense au final gérer mes textures ( et mes objets en général ) de différentes manière, en distinguant ceux dont on peux se séparé dés qu'il ne sont plus utilisé, ceux qu'on peut supprimer a un moment donné et ceux que l'on peux gardé jusqua la fin de vie du Manager de ressources .

    Ma première version du code illustre le comportement numéro 3 .

    Je cherche donc a simulé le comportement numéro 1 dans un premier temps.

    Je viens de tester, en utilisant des weak_ptr dans ma "map" et en retournant "Map_Texture[ID].lock()" dans ma fonction get(), mais il semble que les texture soit créer / détruite aussitot ... Je vais voir comment contourner cela .

    EDIT : Je ne connais vraiment pas weak_ptr, alors je vais faire un peu de lecture pour voir son fonctionnement au lieu de tatonner comme un manchot

  5. #5
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Février 2006
    Messages
    943
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 943
    Points : 1 156
    Points
    1 156
    Par défaut
    En effet, je ferais un gestionnaire qui ne detruit pas automatiquement les textures car sinon tu va te retrouver a faire des chargements et des dechargements a chaque fois ce qui reduit l'interet du gestionnaire.

    Dans ce cas tu as plusieurs possibilité :
    - charger tes objets au debut (pour de petits projets c'est impec) et smart pointers tues tout a la fin.
    - charger dinamiquement et mettre en dur dans ton programme ce qu'il faut eleminer.

    Pour la redefinition de new/delete/new[]/delete[] c'est un autre but.
    Tu peux avoir besoin de faire des classes de bases que tu veux fiables/rapides/compactes dans ce cas tu veux pas gerer de compteurs, meme leger. Tu declare tes surcharges en mode debug et ainsi tu es sur d'avoir quelque chose de correcte. Ensuite tu enleves la surcharge.

    En tout cas les deux rendent de grands services

  6. #6
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    En effet, je ferais un gestionnaire qui ne detruit pas automatiquement les textures car sinon tu va te retrouver a faire des chargements et des dechargements a chaque fois ce qui reduit l'interet du gestionnaire.

    Dans ce cas tu as plusieurs possibilité :
    - charger tes objets au debut (pour de petits projets c'est impec) et smart pointers tues tout a la fin.
    - charger dinamiquement et mettre en dur dans ton programme ce qu'il faut eleminer.
    Tout à fait d'accord Ca recoupe d'ailleur mon message précédent

    Pour la redefinition de new/delete/new[]/delete[] c'est un autre but.
    Ma fois ... ca ne peux que me faire du bien de mettre le nez plus en pronfondeur dans tout ca, ca m'aidera à combler des lacunes également ! Dés que j'ai le temps .... c'est en projet !


    Concernant les weak_ptr, je viens de voir quelques exemples, et j'ai comprit pourquoi mes textures étaient créer / détruite instantanément .

    En effet, je cré le weak_ptr AVANT que mon objet ai acquis un shared_ptr ... donc forcément le weak_ptr part en fumé ... je vais chercher comment régler le problème !

    ( pour info , le code correcpondant avec un ouput )
    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
    class CTextureManager
    {
    public:
    	boost::shared_ptr<CTexture> Get(int ID)
    	{
    		if ( Map_Texture.find(ID) == Map_Texture.end() )
    		{
    			Map_Texture[ID] = boost::shared_ptr<CTexture>( new CTexture(ID)) ;
    		}
    		if ( ! Map_Texture[ID].lock())
    			std::cout << " [ Erreur ] " << std::endl ;
     
    		return Map_Texture[ID].lock() ;
    	}
    private :
    	std::map <int, boost::weak_ptr<CTexture> > Map_Texture ;
    };

    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
    int main(int argc, char *argv[])
    {
    	SDL_Init(0);
    	CTextureManager M ;
     
    	CItem I;
    	{
    	CItem I1,I2 ;
     
    	I.T = M.Get(0);
    	I1.T = M.Get(1);
    	I2.T = M.Get(1) ;
    	}
    	std::cout << " ------------------------ " << std::endl ;
     
     
    	SDL_Quit();
     
    	return 0;
    }
    Texture 0 is created
    Texture 0 is destroyed
    [ Erreur ]
    Texture 1 is created
    Texture 1 is destroyed
    [ Erreur ]
    [ Erreur ]
    ------------------------

  7. #7
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Pourquoi tu fais un shared_ptr<> tout de suite et pas un weak_ptr<> ?

  8. #8
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    Tu veux dire lors de l'ajout ? Car ca ne compilera pas, si j'ai bien comprit, un weak_ptr est bati sur une ressource déja existante .

    En testant ca donne ca comme erreur :
    error C2440: 'type cast' : cannot convert from 'CTexture *' to 'boost::weak_ptr<T>'
    with
    [
    T=CTexture
    ]

  9. #9
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    C'est vrai, j'avais oublié
    CTexture est une de tes textures ? Tu peux essayer en la dérivant de enable_shared_from_this ?

  10. #10
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    La classe CTExture est telle qu'elle est décrite plus haut .

    Pour les enable_shared_from_this, j'ai comprit le principe mais je ne vois pas ou ca serait utile, de plus en recompilant ma classe dérivé de enable_shared_from_this j'ai une erreur de compilation :

    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
    #include <boost/enable_shared_from_this.hpp>
     
    class CTexture: public enable_shared_from_this<CTexture>
    {
    public :
    	CTexture(int ID_t)
    	{
    		ID = ID_t ;
    		std::cout << "Texture " << ID << " is created" << std::endl ;
    	}
    	~CTexture()
    	{
    		std::cout << "Texture " << ID << " is destroyed" << std::endl ;
    	}
     
    	/*boost::shared_ptr<CTexture> GetPtr()
    	{
    		return shared_from_this();
    	}*/
    private :
    	int ID ;
    };
    L'erreur :
    error C2504: 'enable_shared_from_this' : base class undefined
    Désolé je manque de temps, je reveins d'ici deux heure pour appronfondir ca .

  11. #11
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Les weak_ptr ne me paraissent pas faits pour cela. Car, quand tous les "clients" de l'objet auront été détruits et auront fait passer le compteur à 0, il restera alors un weak_ptr pointant vers 0 dans la map. Ce me parait moyen.




    Juste une idéee comme ça:

    Je verrais plutôt un systême de smart-handles. Le truc, c'est que tu ne renvoies plus directement le pointeur, mais un truc qui y ressemble et qui fait une indirection.
    Cette fois ce smart-handle est créé avec une référence vers le gestionnaire d'handles, et l'id (peut être le pointeur brut pour des raisons de simplicité d'implémentation). Ces handles implémentent les opérateurs que l'on retrouve sur les pointeurs (*, ->). Mais lorsque leur compteur tombe à 0, cette fois plutôt qu'un delete, on réalise un appel à la seule fonction autorisée à libérer ces ressources : une fonction du gestionnaire de handles.

    On doit pouvoir implémenter facilement le smart-handle à comptage de références à l'ade de boost::shared_ptr. Il faut juste me pas oublier que seul le gestionnaire d'handlers est autorisé à construire des ressources enveloppées dans les smart-handles, et que l'opération de libération est fournie par le gestionnaire d'handles.



    Il doit aussi y avoir la solution d'implémenter une flyweight-factory qui est définie à l'aide de shared_ptr<>, qui renvoie des shared_ptr<>. Et qui dispose d'une fonction de récupération de données peu utilisées (celles qui ont un compteur =1 (1 pour la référence stockée dansla factory). Cela va revenir à implémenter un GC. Soit une optimisaton qui peut s'avérer un peu compliquée à mettre en oeuvre.

  12. #12
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Février 2006
    Messages
    943
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 943
    Points : 1 156
    Points
    1 156
    Par défaut
    En effet le ramasse miette est peut-etre un peu barbare pour un simple gestionnaire de textures.

    D'autant plus que ce n'est pas parceque la texture n'est pas pointée que l'on en as pas besoin.

    A reflechir.

  13. #13
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    Je verrais plutôt un systême de smart-handles. Le truc, c'est que tu ne renvoies plus directement le pointeur, mais un truc qui y ressemble et qui fait une indirection.
    Je vois le principe, mais une indirection ca fait un peu lourd pour ca non ? Enfin, c'est pas énorme non plus, mais j'aimerai éviter un niveau d'abstraction supplémentaire et tenter de voir si en changeant un peu mon modèle de conception je n'arrive pas a retomber sur mes pattes .... enfin l'idée est à considérer .

    Il doit aussi y avoir la solution d'implémenter une flyweight-factory qui est définie à l'aide de shared_ptr<>, qui renvoie des shared_ptr<>. Et qui dispose d'une fonction de récupération de données peu utilisées (celles qui ont un compteur =1 (1 pour la référence stockée dansla factory). Cela va revenir à implémenter un GC. Soit une optimisaton qui peut s'avérer un peu compliquée à mettre en oeuvre.
    Il est temps d'aller voir mon amis google, le pattern factory je ne connais pas Quand à GC ... je ne sais même pas à quoi correspondent les initiales .

    Enfin bref, il est temps de réfléchir
    Merci à tous !

  14. #14
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par Clad3
    La classe CTExture est telle qu'elle est décrite plus haut .

    Pour les enable_shared_from_this, j'ai comprit le principe mais je ne vois pas ou ca serait utile, de plus en recompilant ma classe dérivé de enable_shared_from_this j'ai une erreur de compilation :

    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
    #include <boost/enable_shared_from_this.hpp>
     
    class CTexture: public enable_shared_from_this<CTexture>
    {
    public :
    	CTexture(int ID_t)
    	{
    		ID = ID_t ;
    		std::cout << "Texture " << ID << " is created" << std::endl ;
    	}
    	~CTexture()
    	{
    		std::cout << "Texture " << ID << " is destroyed" << std::endl ;
    	}
     
    	/*boost::shared_ptr<CTexture> GetPtr()
    	{
    		return shared_from_this();
    	}*/
    private :
    	int ID ;
    };
    L'erreur :


    Désolé je manque de temps, je reveins d'ici deux heure pour appronfondir ca .
    c'est dans le namespace boost, comme pour tout le reste...

    Luc > tout à fait, c'est pour ça que je préconisais de faire un 2ème test sur la validité du pointeur.

  15. #15
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    c'est dans le namespace boost, comme pour tout le reste...
    Grmpf c'était tout bête ! merci

  16. #16
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Citation Envoyé par Miles
    Luc > tout à fait, c'est pour ça que je préconisais de faire un 2ème test sur la validité du pointeur.
    Mais cela ne va rien désentregistrer. Dans mes souvenirs, le weak_ptr observe la destruction et ne fait qu'un RAZ.
    Ceci dit, le désenregistrement peut être fait si on part sur de l'intrusif : l'objet sait qu'il est géré dans un gestionnaire, et agit en conséquence dans son destructeur.


    Pour l'indirection, un pointeur, c'est une indirection. Et la solution que je proposais ne coutait pas plus cher qu'un boost::shared_ptr<> vu qu'elle peut reposer dessus pour être mise en oeuvre ^^
    Accessoirement, comme on dit souvent : un code qui va vite dans le mur a un intérêt assez nul. Et le RAII est un bon moyen d'avoir rapidement un code robuste qui fait ce qu'on lui demande.

  17. #17
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    Pour en revenir a ton idée de smart-handle, si j'ai bien compris ( et la c'est pas gagné ), l'idée est de stocker une map de " int,CTexture* " dans notre manager. Et d'envelopper pointeur et donc le comptage de référence dans une classe "handle" en redéfinissant * et -> pour que les opération est liue sur le smart_ptr menbre et non sur la classe elle même .
    ( si c'est bien ca, j'essairai de voir l'implémentation pour voir les problèmes qui se posent )

    Enfin l'idéal serait de simplement faire en sorte que le smart_ptr de la map du manager ne compte pas pour une référence .... mais a part l'idée du weak_ptr je ne vois pas .

    Enfin j'ai bien une idée mais ca fait pas très propre :

    En dérivant toute nos classes de enable_shared_from_this, et en passant a la fonction get() un pointeur sur l'objet demandant la texture ( un this a priori vu que la ressource est souvent acquise a lintérieur meme de l'objet ), on doit pouvoir s'en sortir ...peut-etre ( car je veint d'essayer, ca va être assez bancal si jamais ca marche ).

    Bref j'attend de voir si j'ai bien suivit l'idée du smart-handle et en attendant je cherche du coté des weak_ptr

  18. #18
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Ce ne doit certainement pas compiler.

    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
     
    struct Texture : boost::noncopyable {
       // trucs publics:
    private: // protégé si héritage
       ~Texture() ; // virtuel si héritage
       Texture(int ID, Args const&);
     
       friend class TexturesManager;
    };
     
    class TexturesManager {
    private: // pas nécessaire avec "class"
        struct Releaser {
            Releaser(TexturesManager & manager) : manager_(manager) {}
            void operator()(Texture const* t) const {
                manager_ . release(t);
            }
        private:
            TexturesManager & manager_;
        }; // TexturesManager::Releaser
     
    public:
        typedef boost::shared_ptr<Texture> handle_type;
     
        handle_type createTexture(Args const& args) {
            const int ID = s_buildNewID();
            Texture * t = new Texture(ID, args); // Ami
            handle_type handle(t, Releaser(*this));
            registerTexture(handle.get());
            return handle;
        }
     
    private:
        void release(Texture const* t) // throw()
        {
            unregisterTexture(t);
            delete t; // Ami
        }
     
        void registerTexture(Texture * t) {
            assert(t && "Cannot register nil texture");
            textures_[t->getID()] = t;
        }
     
        void unregisterTexture(Texture * t) {
            assert(t && "Cannot unregister nil texture");
            textures_.erase(t->getID());
        }
     
        static int s_buildNewID() {
            static int sl_ID = 0; // pas du tout thread-safe, ...
            return sl_ID ++;
        }
     
        std::map<int, Texture*> textures_; // bien un simple pointeur brut(!)
    };
     
    ....
    {
        TexturesManager::handle_type uneTexture( tm.create(arg1) );
        uneTexture -> doSomething();
        // pas de delete, ni rien ...
        // et la texture est détuite et retirée du manager.
    }
    Edit: petite erreur + boot::noncopyable

  19. #19
    Membre habitué
    Inscrit en
    Octobre 2004
    Messages
    616
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 616
    Points : 164
    Points
    164
    Par défaut
    En 30 secondes avant de partir au taff, merci je testerai ce code dés que je pourrais

    Sinon j'ai pensé a 2 autres méthodes qui sont simples et devraient marcher mais ont chacunes une petit défaut, j'aimerais votre avis dessus .

    La première, dans chaque objet dont je veux une durée de vie limité pour la texture, j'apelle un e fonction Delete(ID) dans le destructeur de l'objet ( cette fonction supprimera la texture si le nbre de référence du smart-ptr est de 1 .... 1 car il y en un dans la "map" ) .
    Ca présente le défaut d'être moche et surtout de devoir penser dans chaque classe à apeller la fonction de l'extérieur, je suis pas chaud .

    Ma deuxième idées est un peu plus élégante mais j'ai un tout petit doute ( encore que, ca demande réfléxion ) sur la rapidité de celle-ci .
    Lors de la création de mes texture, je passe un flag en plus de l'ID de celle-ci pour savoir si leur durée de vie doit etre limité ou pas .
    A chaque frame, j'exécute une fonction CollectDeadTexture() dans mon textureManager qui va se charger de supprimer les texture a durée de vie limité ( stocké dans une seconde map probablement ou dans un autre conteneur si il y a plus judicieux ... ) et dont le nbre de référence du smart_ptr restant est de un .
    [ Bon ca fait une boucle sur toutes ces textures a cahque frame, alors que dans l'idéal j'aimerai une simple opération lorsque qu'il y en a besoin ... mais bon, c'est deja pas mal ^^ ]


    Qu'en pensez-vous ?

  20. #20
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Février 2006
    Messages
    943
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 943
    Points : 1 156
    Points
    1 156
    Par défaut
    GC est Garbage Collector ou Ramasse Miette en francais.
    C'est le systeme Java utilisé pour detruire les objet inutilisé, d'ou l'inutilité du delete.

    La solution reste couteuse et difficile a implementer car tu doit referencé tout tes pointeurs puis toutes les N ms les parcourir pour supprimer ceux qui sont inutiles.

    Pour la flyweight-factory c'est un pattern fabrique assez interressant et si je me souvient bien il y a un exemple dans le tutoriel sur les moteurs 3D chapitre 4 ou 5 sur les ressources justement si tu l'as pas lu c'est le moment.

Discussions similaires

  1. Réponses: 10
    Dernier message: 29/03/2009, 17h24
  2. Exemple concret de jointures
    Par Lenezir dans le forum Langage SQL
    Réponses: 2
    Dernier message: 01/02/2008, 17h56
  3. Memory Managment dans vos programmes
    Par Clad3 dans le forum C++
    Réponses: 11
    Dernier message: 25/07/2006, 02h25
  4. heap memory manager
    Par flames dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 02/06/2006, 13h17

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