Gestion des pointeurs sur instance - C++ - Programmation
Marsh Posté le 02-06-2013 à 13:23:02
Je up le topic, j'ai pondu un code
Donc, le système vérifie que les pointeurs sont valides / mettent à jour la liste uniquement si SAFEPOINTERS est défini, niveau perfs ça donne :
Benchmark (SafePointers enabled) :
Performed in 85.3783 ms.
Benchmark (SafePointers disabled) :
Performed in 4.22425 ms.
Benchmark (Naked Pointers) :
Performed in 2.01364 ms.
Et voilà le code de la class :
Code :
|
Si vous avez des conseils pour améliorer la qualité du code ou la vitesse d'exécution, je suis preneur
edit : Désolé, j'arrive pas à avoir la bonne mise en page, y'a des lignes qui sont très mal foutu
Marsh Posté le 02-06-2013 à 16:17:31
deja utilisait un ruc ecrit proprement genre boost::shared_ptr me parait mieux que d'ecrire une n-ieme classe de gestion de pointeurs.
Voir aussi si unique_ptr n'est pas plus adapté.
Marsh Posté le 02-06-2013 à 16:37:35
Mais si j'ai bien compris, les shared_ptr ont un système de comptage de références, et dès que ça atteint 0 l’élément est supprimé.
Or moi, je veux que si le propriétaire de la variable la supprime, tout les pointeurs sont automatiquement mis à NULL (Ce qui se passe dans ma class WatcherPointer en gros).
Pour ce qui est de unique_ptr, c'est pas juste un pointeur qu'on ne peut pas copié et qui est supprimé lors de la fin de son cycle ?
Marsh Posté le 03-06-2013 à 18:46:14
Ok je viens de voir qu'en fait, y'avait les std::weak_ptr qui permettent de faire plus ou moins ce que je veux.
En gros, si j'ai bien compris, les weak_ptr sont comme des shared_ptr sauf qu'ils n'incrémentent pas le nombre de références, et dès lorsque que le tout les shared_ptr sont reset, ils sont marqués comme expirés c'est ça ?
Mais le soucis, c'est que pour modifier une valeur du pointeur (ou simplement lire), il faut absolument régénérer un shared_ptr à partir du weak_ptr, et ça serait chiant à mettre en place un système pour bypasser toute la vérification des pointeurs lors de la compilation en release.
edit : D'un autre côté, le fait de devoir régénérer un shared_ptr fait que je suis sûr à 100% qu'en cas d'usage sur un thread séparé, mon pointeur sera valide et ne pourra pas être supprimé lors d'un appel de fonction..
Marsh Posté le 04-06-2013 à 14:29:10
C'est quoi, ton cas de figure ?
Parce que si c'est pour gérer des ressources, je doute que tu veuilles vraiment "supprimer" ta ressources alors que tu as encore des références dessus. C'est pour faire un mécanisme de reload quand ta donnée sur le disque change ?
Marsh Posté le 04-06-2013 à 15:34:50
Non, c'est pas une ressource mais simplement une instance qui est un mesh dans une scène.
Mais le cas de figure serait peut-être plus clair pour un gestionnaire d'objet d'un jeu :
Mettons j'ai 30 000 objets dans un jeu qui soient des ennemis, et un qui soit un joueur.
Les 30 000 ennemis auraient en attribut un pointeur pour savoir qui ils ciblent par exemple (qui est à NULL s'il ne cible personne).
Si jamais le joueur est supprimé, dans ce cas tout les ennemis qui avaient leur pointeur de cible sur le joueur sera automatiquement mit à NULL.
En gros, si j'ai bien compris ce genre de système est faisable avec les std::shared_ptr / std::weak_ptr :
Chaque ennemi aurait un weak_ptr pour la cible, et le gestionnaire d'objet serait une liste de std::shared_ptr, donc si jamais le joueur est supprimé (plus aucun shared_ptr sur lui), normalement tout les weak_ptr seront marqués comme invalide.
Mais finalement, je pense opter pour un système uniquement basé sur les shared_ptr, ou alors une classe encapsulant les shared_ptr, qui aurait une info supplémentaire (une variable mis à true si le possesseur de ce pointeur cherche à supprimer la valeur), qui provoquerait automatiquement une remise à zero du shared_ptr qu'elle encapsule (un truc dans le genre, c'est pas encore bien clair dans ma tête )
Le soucis, c'est que tout ce système m'inquiète un peu niveau perfs, j'ai peur de finir par avoir un truc très safe, mais très lent..
Marsh Posté le 04-06-2013 à 15:40:52
pour ce genre d'évènement que tu décris, je aurais une préférence pour avoir les N ennemis qui ont un pointeur et ne se soucient pas de son passage à NULL, et, plutôt un système d'évènement robuste pour notifier de la disparition de l'entité qu'ils ciblent.
Marsh Posté le 04-06-2013 à 15:49:07
Ah oui, j'avais pas pensé à ça (même si je pense que dans le cas des meshes c'est pas trop possible)
Mais pour un tel système, c'est quoi la meilleur technique ? Parce que re-parcourir toute la liste d'objet dès qu'un objet est supprimé pour tenir toutes les instances au courant, c'est un peu lourd
Marsh Posté le 04-06-2013 à 15:59:14
Terminapor a écrit : Ah oui, j'avais pas pensé à ça (même si je pense que dans le cas des meshes c'est pas trop possible) Mais pour un tel système, c'est quoi la meilleur technique ? Parce que re-parcourir toute la liste d'objet dès qu'un objet est supprimé pour tenir toutes les instances au courant, c'est un peu lourd |
dans ma boîte, on a un système d'évènement agnostique qui accepte juste une clé. Tu peux t'enregistrer de manière globale ou avec une clé donnée (Edit/précision : c'est un enregistrement actif en fonction des intérêts de ton observer, pas un système de messages pour tout le monde). Ca te fait atterrir dans des ensembles d'observers différents. Du coup, quand tu signales la disparition de ton truc, tu files son identifiant (quitte à ce que ce soit directement le pointeur de la ressource, hein) et du coup, ca ne va notifier que ceux qui sont intéressés par cette clé là ou l'intégralité de ces messages. Ca garde raisonnable le volume d'observers
Pour ton histoire de mesh, ca me chiffonne tout de même un peu que ce ne soit pas justement une ressource, après, c'est peut-être juste une question de terminologie, hein.
Marsh Posté le 04-06-2013 à 16:55:13
Mais pour un tel système, faut bien à un moment parcourir les événement, non ?
Sachant qu'il peut avoir énormément de création / suppression de meshes, ça risque de beaucoup ralentir tout le processus si j'ai des parcours à faire à chaque fois
Pour ce qui est du mesh, c'est simplement qu'une fois qu'il est viré de la scène, il n'a plus aucune utilité (il sert juste à être dessiné par la scène elle-même), donc dès lors que la scène le supprime, vaut mieux libérer direct la mémoire, non ?
Au pire, c'est qu'une petite classe d'environ 200 octets, mais bon
Marsh Posté le 04-06-2013 à 17:13:32
J'ai tendance à partir dans l'optique inverse : ton mesh est une ressource, si ton manager de meshes s'aperçoit qu'il est le seul à avoir des références sur un mesh donné, alors il peut le détruire, sinon, c'est que quelqu'un a besoin de le rendre. Je trouve surprenant de garder un pointeur sur une donnée graphique si c'est pas pour qu'elle soit dans ta scène.
Pour en revenir aux évènements à parcourir, à nouveau, je vois mal ce qui peut référencer tes meshes et qui ne te donne pas de contrainte forte sur la durée de vie de ta donnée, mais tpar exemple, tu peux avoir un évènement par type de message (l'annonce de la suppression d'une ressource est un message à part entière), chaque évènement a son propre pool d'observers globaux (qui seront systématiquement notifiés) plus un conteneur associatif clé -> pool d'observers (ici, la clé est un identifiant unique de ta ressource). Tes observers devraient en toute logique être assez peu nombreux, non ?
Et sinon, aussi, je ne sais pas si la suppression immédiate est forcément une bonne chose. C'est souvent moins contraignant de partir du principe que tu marques pour suppression et que tu vas éliminer tout ce qui doit l'être à un point bien particulier. Ca t'évite en grande partie de te soucier de multi-threading suivant l'endroit où tu te dis que tel truc ne sera plus utile
Marsh Posté le 04-06-2013 à 17:51:31
Effectivement j'avais pas pensé le problème dans l'autre sens, puisque techniquement si un mesh est supprimé, c'est que l'objet qui le manipule est aussi supprimé.
Pour ce qui est du gestionnaire d'événements, c'est une bonne idée ça m'évitera des fonctions de traitements d'événements de partout, faudrait que je check aussi un peu comment le système des QConnect est fat parce que ça peut être très pratique
Globalement, je verrais tout ça un peu sur le tas, merci pour ton aide !
Marsh Posté le 02-06-2013 à 00:37:16
Bonsoir
Je cherche le type de pointeur le plus approprié pour gérer des instances d'une collection, en gros :
J'ai une class qui contrôle des objets pour un moteur de rendu, elle gère leur cycle de vie (allocation, suppression).
ce que je voudrais, c'est avoir le type de pointeur le plus approprié pour gérer les pointeurs sur ces objets, un comportement comme celui-ci :
J'avais fait une implémentation assez truellique de ce genre de système, où les "vrais" pointeur (P dans ce cas) avaient en attribut une liste de tout les pointeurs qui pointaient sur lui, et lorsqu'il était supprimé, je rendait les autres pointeurs invalide, mais ça me semble pas très adapté. (Au pire, je peux activer ce système uniquement en debug..)
Merci pour votre aide
edit : Je viens de penser au sf::Resource_ptr de la SFML, j'ai regardé le code source et c'est la même chose que ma version truellique, donc c'est le seul moyen de faire ?
Message édité par Terminapor le 02-06-2013 à 00:52:33
---------------
Perhaps you don't deserve to breathe