Bonjour,

Voilà après plusieurs tentatives et lectures de forums/articles/faq j'ai enfin réussi a faire mon petit gestionnaire de ressources.

Cependant j'ai du utiliser plusieurs concepts que je ne maîtrise pas vraiment...
Donc je suis persuadé qu'il existe de bien meilleurs moyens d'écrire ce que je cherche à faire.

J'aimerai, si possible, avoir vos avis et remarques sur les corrections à apporter. Je me lance que depuis peu dans la "généricité" .

L'idée et la suivante :
Pour chaque nouveau type de ressource, il suffit d'écrire une classe de politique comme celle donnée en example.

Pour vous épargner la lecture de tout le code, il y'a une forward déclaration un peu bizzare. L'utilisation du mot clé friend dans le pointeur de resource. Et la classe de politique DOIT retourner un pointeur. Voilà les points qui m'embêtent.

Resource.h
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
 
#ifndef RESOURCE_H
#define RESOURCE_H
 
#include "managers/resource/ResourceManager.h"
 
template<class TResourcePolicy>
class CResource
{
    friend class CResourceManager;
 
public:
    ~CResource()
    {
        CResourceManager::get().template free<TResourcePolicy>(m_filename);
    }
 
    typename TResourcePolicy::type operator*()
    {
        return *m_ptr;
    }
 
private:
    CResource(){}
 
    typename TResourcePolicy::type*      m_ptr;
    QString                              m_filename;
};
 
#endif // RESOURCE_H
TexturePolicy.h
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
 
#ifndef TEXTUREPOLICY_H
#define TEXTUREPOLICY_H
 
#include <QString>
#include <QtOpenGL>
 
struct TTexturePolicy
{
    typedef GLuint type;
 
    static GLuint* load(QString filename)
    {
        GLuint* value = new GLuint;
        *value = 2;
        return value;
    }
};
 
#endif // TEXTUREPOLICY_H

ResourceManager.h
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
 
#ifndef RESOURCEMANAGER_H
#define RESOURCEMANAGER_H
 
#include <QHash>
#include <QObject>
#include <QString>
 
template<class TResourcePolicy>
class CResource;
 
#include <iostream>
 
class CResourceManager : QObject
{
    Q_OBJECT
 
public:
    /*============================================================================
      Obtenir l'instance courante du gestionnaire de ressources.
      return :
        L'instance courante du gestionnaire de ressources.
    ==============================================================================*/
    static CResourceManager& get();
 
    /*============================================================================
      Charge une ressource si nécessaire, et incrémente le nombre de références.
      TResourcePolicy :
        Politique de chargement utilisée.
      filename :
        Chemin d'accès à la ressource.
      return :
        La ressource.
    ==============================================================================*/
    template<typename TResourcePolicy>
    CResource<TResourcePolicy> load(QString filename);
 
    /*============================================================================
      Décrémenter le nombre de références à la ressource filename.
    ==============================================================================*/
    template<typename TResourcePolicy>
    void free(QString filename);
 
signals:
    /*============================================================================
      Signal de chargement de ressource depuis le disque.
      filename :
        Nom du fichier chargé.
    ==============================================================================*/
    void sigResourceLoaded(QString filename);
 
    /*============================================================================
      Signal de libération de ressource..
      filename :
        Nom de la ressource libérée.
    ==============================================================================*/
    void sigResourceDestroyed(QString filename);
 
private:
    /*============================================================================
      Constructeur & destructeur privé, cette classe est un singleton.
      Utiliser CResourceManager::get() pour obtenir l'instance en cours.
    ==============================================================================*/
    CResourceManager();
    ~CResourceManager();
 
    /*============================================================================
      Structure de représentation d'une ressource.
    ==============================================================================*/
    typedef struct
    {
        void*   m_ptr;
        quint64 m_refs;
    } TResource;
 
    // Données membres
    QHash<QString, TResource> m_resources;
};
 
// Définition de la méthode template load
template<typename TResourcePolicy>
CResource<TResourcePolicy> CResourceManager::load(QString filename)
{
    QHash<QString, TResource>::iterator it = m_resources.find(filename);
    if(it == m_resources.end())
    {
        TResource resource;
        resource.m_ptr = TResourcePolicy::load(filename);
        resource.m_refs = 0;
        it = m_resources.insert(filename, resource);
 
        emit sigResourceLoaded(filename);
        std::cout << "RESOURCE LOADED !" << std::endl;
    }
 
    it.value().m_refs++;
    std::cout << "REFS : " << it.value().m_refs << std::endl;
 
    CResource<TResourcePolicy> resource_ptr;
    resource_ptr.m_filename = filename;
    resource_ptr.m_ptr = (typename TResourcePolicy::type*) it.value().m_ptr;
    return resource_ptr;
}
 
// Définition de la méthode template free
template<typename TResourceType>
void CResourceManager::free(QString filename)
{
    QHash<QString, TResource>::iterator it = m_resources.find(filename);
    if(it != m_resources.end() && --it.value().m_refs == 0)
    {
        delete (typename TResourceType::type*) it.value().m_ptr;
        m_resources.erase(it);
 
        emit sigResourceDestroyed(filename);
        std::cout << "RESOURCE DESTROYED !" << std::endl;
        std::cout << "REFS : " << it.value().m_refs << std::endl;
    }
}
 
#endif // RESOURCEMANAGER_H
ResourceManager.cpp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
 
#include <QHash>
 
#include "managers/resource/ResourceManager.h"
 
CResourceManager& CResourceManager::get()
{
    static CResourceManager s_instance;
    return s_instance;
}
 
CResourceManager::CResourceManager(){}
CResourceManager::~CResourceManager(){};
main.cpp
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
 
 
#include <QApplication>
#include <QtOpenGL>
 
#include "managers/resource/Resource.h"
#include "managers/resource/ResourceManager.h"
#include "managers/resource/TexturePolicy.h"
 
#include <iostream>
 
void foo(){
    CResource<TTexturePolicy> texture_id = CResourceManager::get().load<TTexturePolicy>(QString("test"));
    CResource<TTexturePolicy> texture_id2 = CResourceManager::get().load<TTexturePolicy>(QString("test"));
    std::cout << *texture_id << std::endl;
}
 
int main(int argc, char* argv[]){
 
    QApplication app(argc, argv);
 
    foo();
    CResource<TTexturePolicy> texture_id = CResourceManager::get().load<TTexturePolicy>(QString("test"));
    std::cout << *texture_id << std::endl;
 
    return app.exec();
}