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 :

Mise à jour d'un Gestionnaire de Ressource


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 12
    Par défaut Mise à jour d'un Gestionnaire de Ressource
    Bonjour, je suis actuellement en train de réfléchir à la façon de faire un Gestionnaire de Ressource.
    Je me suis penché sur la façon de faire de Laurent dans son tutoriel sur la création d'un ResourceManager. J'ai retenu l'idée de passer par un MediaManager afin de gérer efficacement les différents type de média qui seront proposés dans mon application. Cependant, je reste perplexe sur la façon de réaliser mon ResourceManager proprement.

    Voici mon problème:
    J'utilise les shared_ptr que propose la bibliothèque Boost. J'ai donc une map définis comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef boost::shared_ptr<Resource> ResourcePtr;
    std::map<std::string, ResourcePtr> ressources;
    Jusque là, tout va bien. J'ai réussi à gérer la demande de ressource, la création de la ressource si celle-ci n'est pas présente au sein de mon manager. Cependant, il se peut que la ressource ne soit plus utilisé à un instant t. Je voudrai donc la supprimer de ma map. Or, j'ai envie que cette tâche soit automatisé, et que ça soit le ResourceManager qui le fait automatiquement.

    Ma première solution est:
    Passer mon ResourceManager en singleton. Puis dans le destructeur d'une resource, je fais appel à une méthode de mon ResourceManager:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void update(Resource* res) {
        rechercher la ressource dans la map
     
        SI compteur de la ressource EGAL A 1 ALORS
            supprimer ressource de la map
        FIN SI
    }
    En effet, si le compteur est égal à 1, cela veut dire qu'il n'est plus pointé que par mon shared_ptr de ma map. Et donc je peux le supprimer de la map.

    Soucis: Le Singleton.
    Je n'ai rien contre ce pattern, mais ici, je l'utilise uniquement pour avoir un accés global à mon ResourceManager, je pense pas que ça soit une bonne façon de faire.

    Deuxième Solution:
    Recréer une classe shared_ptr, celle-ci prendra en paramètre un foncteur. A ce foncteur dans son constructeur je lui passerai l'adresse du ResourceManager. Comme ça, à chaque fois qu'un shared_ptr est détruit, j'appelle ce foncteur. Puis le foncteur appellera la fonction update que je viens d'exposer plus haut.


    J'aimerai savoir s'il n'existerai pas un pattern qui résoudrait mon problème ? J'ai l'impression de me prendre la tête, mais j'aimerai faire un ResourceManager qui ne me prenne plus la tête par la suite et qui soit vraiment automatisé.

    En esperant avoir votre aide, je vous remercie d'avance.


    eXa

  2. #2
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 12
    Par défaut
    C'est uniquement pour la destruction de l'objet pointé, pas du shared_ptr.
    La fonction ne sera appellée que lorsque delete sera appellé pour détruire l'objet pointé par le shared_ptr. :/

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Ce qui tu essaies de recréer, c'est Boost.Flyweight en moins bien.

  5. #5
    Membre éclairé

    Profil pro
    Étudiant
    Inscrit en
    Juin 2006
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2006
    Messages : 78
    Par défaut
    Tu peut garder un weak_ptr dans ton manager et fournir un shared_ptr. Le surcoût en mémoire est assez minime, et rien ne t'empêche de faire des passages dans la map de temps en temps pour vérifier leur validité et supprimer ceux qui ne le sont pas.

    Tant qu'un endroit de ton code possède la ressource (à travers un shared_ptr), tes weak_ptr restent valide et un autre endroit peut donc demander la même ressource. Si par contre, plus aucun shared_ptr ne pointe vers la ressource, alors le weak_ptr n'est plus valide, et tu re-créer la ressource.

    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
    typedef boost::shared_ptr<Resource> ResourcePtr;
     
    class ResMng {
    public:
    	RessourcePtr create(const string & id) {
    		// lock ressources_mutex
    		std::map<std::string, RessourcePtr_weak>::iterator it =
    			ressources.find(id);
    		if (it != ressources.end()) {
    			RessourcePtr ret = it->second.lock();
    			if (ret) {
    				// unlock ressources_mutex
    				return ret;
    			}
    		}
    		RessourcePtr ret(new Ressource);
    		ressources[id] = RessourcePtr_weak(ret);
    		// unlock ressources_mutex
    		return ret;
    	}
     
    private:
    	typedef boost::weak_ptr<Ressource> RessourcePtr_weak;
    	std::map<std::string, RessourcePtr_weak> ressources;
    	// Mutex ressources_mutex;
    };

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 12
    Par défaut
    Je vous remercies pour vos deux réponses.
    Je vais retenir la solution de Aszarsha.
    Merci encore d'avoir prit la peine de ma répondre, sujet résolu.


    eXa

  7. #7
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Tout dépend de ce que tu veux faire en resource-manager....
    Mais en général, le resource-manager à deux rôles:
    - Lire les resources (initialiser les objets Resource).
    - Gérer la durée de vie de ces resources.

    L'utilisation de shared_ptr est donc inutile (voire dangereuse). Le seul "propriétaire" de la resource c'est le manager... Si d'ailleurs c'est lui qui fait le new, c'est aussi lui qui doit faire le delete !

    Si cette unique argumentation ne vous convainc pas imaginons:
    (en bleu la version 'shared_ptr' coté client, en rouge la version 'pointeur' coté client, en noir, la version similaire).

    Toto a besoin de la resource Bobo, et la demande au manager.
    => le manager va créer/initialiser/lire la resource (10ms ?)
    Tata a besoin de la resource Bobo, et la demande au manager.
    => le manager va lui renvoyer la même resource.
    Toto n'a plus besoin de Bobo
    Tata n'a plus besoin de Bobo.
    => avec shared_ptr, destruction de la resource
    => avec pointeur simple, le manager peut décider de la destruction de la resoruce (besoin de mémoire), ou la garder en cache quelque part.
    Toto a a nouveau besoin de Bobo
    => le manager va devoir re-créer/initialiser/lire la resource apres avoir parcouru sa map, et s'être rendu compte que son weak_ptr n'est plus valide.
    => avec pointeur simple, le manager va juste renvoyer la resource si elle est en cache, ou... faire comme la première fois: création/initialisation/lecture... Dans tous les cas, c'est plus rapide que la version avec shared_ptr.


    Il y a plusieurs façons de réaliser ça:
    1. Comme le manager a une fonction "acquire" de resource, il a aussi une fonction "release". Tout est géré dans ces deux fonctions. Reste à coder un objet de smart pointer utilisant ces fonctions et le tour est joué.
    2. Les resources ont des fonction clientes "AddRef()" / "Release()" (mais non je ne fait pas du COM sans arrêt ), qui sont appelée par le client, une classe "Resource" de base implémente le compteur d'utilisateur et le pointeur vers le manager responsable de la resource, et appelle le manager dès que la resource est 'utilisée' ou 'plus utilisée'). Cette solution est un poil plus compliquée à programmer, mais bien plus souple (et rapide), permet d'avoir plusieurs managers en parallèle, ...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Mise à jour d'une ressource
    Par jreeman dans le forum REST
    Réponses: 3
    Dernier message: 01/08/2011, 22h49
  2. Ressources non-mises à jour
    Par Invité dans le forum Maven
    Réponses: 4
    Dernier message: 20/01/2010, 12h58

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