Avis et remarques pour améliorer la généricité.
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:
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:
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:
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:
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:
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();
} |