Bonsoir à tous.
J'ai une question qui va sans doute vous sembler très stupide, mais j'avoue que là je bloque..
J'ai un gestionnaire de mémoire qui s'occupe de charger des ressources. Pour ce faire, les ressources sont uniquement construites avec le nom (un id unique), et le chemin vers la ressource sur le disque.
Pour ce faire, j'ai un type abstrait Resource qui a pour membre deux std::string (name et filePath).
Une fois la ressource "préchargée", si un utilisateur demande au manager de ressource l'accès à une d'elle, le manager va regarder si la ressource est complètement chargée ou seulement préchargée.
S'il faut charger réellement la ressource, le manager va appeler une ResourceFactory qui va construire le bon objet et renvoyer un Resource* donc.
Jusque là, ça va..
Maintenant, comment représenter les données (son, image...) dans la classe abstraite Resource?
J'ai tenté avec un void*, mais ça devient assez bizarre à gérer.. J'ai pensé au template, mais je ne pense pas que ça se fera plus simplement (même au contraire...)
Autre question, je voudrais que le manager n'expose pas les ressources. Seulement pour le moment, à part renvoyer un Resource*, je ne vois pas comment faire.. Des idées?
Il me semble que faire ensemble qu'une seule entité ai la responsabilité d'une ressource porte un nom, si jamais vous pouviez me le rappeler...
Voilà le gestionnaire de mémoire:
La ressource abstraite
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166 /* * ResManager.cpp * * Created on: 24 oct. 2010 * Author: seeme */ #include "ResManager.h" #include "Resources/ResourceFactory.h" #include <queue> #include <string> #include <fstream> #include <boost/algorithm/string.hpp> #include "../LogManager/Log.h" using namespace std; void ResManager::clear(){ m_resourceMap.clear(); m_nextResourceHandle = ""; m_currentUsedMemory = 0; m_maximumMemory = 0; } ResManager::ResManager(){ rf = new ResourceFactory(); clear(); } bool ResManager::create(unsigned int nMaxSize){ clear(); setMaximumMemory(nMaxSize); return true; } void ResManager::destroy(){ for(ResMapItor itor = m_resourceMap.begin(); itor != m_resourceMap.end(); ++itor) { delete ((*itor).second); } m_resourceMap.clear(); clear(); } bool ResManager::setMaximumMemory(size_t nMem){ m_maximumMemory = nMem; return checkForOverallocation(); } bool ResManager::reserveMemory(size_t nMem){ addMemory(nMem); if(!checkForOverallocation()) return false; return true; } bool ResManager::destroyResource(HANDLE rhUniqueID){ ResMapItor itor = m_resourceMap.find(rhUniqueID); if(itor == m_resourceMap.end()){ //Error, not found return false; } if(itor->second->getReferenceCount() > 0){ return false; } if(itor->second->getSize() > 0){ itor->second->destroy(); } return true; } Resource* ResManager::getResource(HANDLE rhUniqueID){ //If it's alread loaded, return it ResMapItor itor = m_resourceMap.find(rhUniqueID); if(itor == m_resourceMap.end()){ //Error, not found return NULL; } //Is it loaded? if((*itor).second->getSize() == 0){ //Not loaded yet, load it (*itor).second->create(); m_currentUsedMemory += (*itor).second->getSize(); } //1up on the ref count //(*itor).second //Check memory state checkForOverallocation(); (*itor).second->upRefCount(); return (*itor).second; } void ResManager::releaseResource(HANDLE uniqHandle){ //Desincrement the ref counter m_resourceMap.find(uniqHandle)->second->downRefCount(); } bool ResManager::checkForOverallocation(){ if(m_currentUsedMemory > m_maximumMemory){ //Over memory, need to free a bit; //Remove the resources that are currently not used (refcount = 0) priority_queue<Resource*, vector<Resource*>, ptr_greater<Resource*> > PriQueue; //Look for the most suitable resource. for(ResMapItor itor = m_resourceMap.begin(); itor != m_resourceMap.end(); ++itor){ if(!itor->second->getSize() == 0 && itor->second->getReferenceCount() == 0) PriQueue.push(itor->second); } while((!PriQueue.empty()) && (m_currentUsedMemory > m_maximumMemory)){ unsigned int nDisposalSize = PriQueue.top()->getSize(); PriQueue.top()->destroy(); if(PriQueue.top()->getSize() == 0) m_currentUsedMemory -= nDisposalSize; PriQueue.pop(); } } return true; } void ResManager::setPackageDir(const char* dir){ m_packageDir = dir; } void ResManager::loadPackage(const char* dir){ ifstream file(dir); vector<string> vect; ResourceFactory* rf = Singleton<ResourceFactory>::get(); if (file){ string line; while(getline(file, line)){ if(line.substr(0, 1) != "#"){ boost::split(vect, line, boost::is_any_of("|")); //vect now contains the data needed for the ressource creation. //Here, the factory comes handy.. m_resourceMap.insert(ResMapPair(vect[0], rf->buildResource(vect[0], vect[1], vect[2]))); } } }else{ Log::e("MemoryManager", "Error Loading Package"); } }
La Factory (juste là pour que ça marche pour le moment):
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 /* * Ressource.h * * Created on: 15 oct. 2010 * Author: seeme * * Based on the article in GamePrograming Gem 3.. */ #ifndef RESSOURCE_H_ #define RESSOURCE_H_ #include <cstddef> #include <ctime> #include <iostream> class Resource { public: enum PriorityType{ RES_LOW_PRIORITY = 0, RES_MED_PRIORITY, RES_HIGH_PRIORITY }; Resource(std::string name, std::string path):m_name(name), m_filePath(path){ clear(); } virtual ~Resource(){ destroy(); } virtual void clear(); //Erase all data virtual bool create(){ return false; } virtual void destroy(){}; virtual size_t getSize() = 0; inline void setPriority(PriorityType priority){ m_priority = priority; } inline PriorityType getPriority(){ return m_priority; } inline void upRefCount(){m_refCount += 1;} inline void downRefCount(){ if(m_refCount > 0){ m_refCount --; }else{ //ERROR } } inline void setReferenceCount(unsigned int count){ m_refCount = count; } inline unsigned int getReferenceCount(){ return m_refCount; } virtual bool operator < (Resource& container); private: PriorityType m_priority; unsigned int m_refCount; time_t m_lastAccess; protected: std::string m_filePath; std::string m_name; void* m_data; }; // This class allows an STL object to compare the objects instead of // comparing the value of the objects' pointers. template <class T> class ptr_less { public: inline bool operator ()(T left, T right) { return ((*left) < (*right)); } }; // This class allows an STL object to compare the objects instead of // comparing the value of the objects' pointers. template <class T> class ptr_greater { public: inline bool operator ()(T left, T right) { return !((*left) < (*right)); } }; #endif /* RESSOURCE_H_ */
Et un exemple de 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
27
28
29
30
31
32
33 /* * ResourceFactory.cpp * * Created on: 16 nov. 2010 * Author: seeme */ #include "ResourceFactory.h" #include "TextFile.h" #include "Asset.h" #include "../../LogManager/Log.h" Resource* ResourceFactory::buildResource(std::string name, std::string id, std::string realPath){ Resource* r; if(id == "txt"){ r = new TextFile(name, realPath); return r; } if(id == "asset"){ r = new Asset(name, realPath); return r; } Log::e("RessourceFactory", "Error unknown build parameter"); return NULL; } ResourceFactory::ResourceFactory(){ } ResourceFactory::~ResourceFactory(){ }
Merci d'avance pour tous les conseils que vous pourrez me donner.. Ca fait pas mal de temps que j'avance pas...
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 /* * TextFile.cpp * * Created on: 16 nov. 2010 * Author: seeme */ #include "TextFile.h" #include <fstream> TextFile::TextFile(std::string fileName, std::string realPath):Resource(fileName, realPath) { std::cout << "New Text File "<< fileName << std::endl; } void TextFile::display(std::string a, std::string b, std::string c){ std::cout << a << std::endl; std::cout << b << std::endl; std::cout << c << std::endl; } TextFile::~TextFile() { // TODO Auto-generated destructor stub } bool TextFile::create(){ std::cout<<"Create a textfile: " << m_filePath << std::endl; std::ifstream file(m_filePath.c_str()); if (file){ //Evidement ça marche pas... m_data = static_cast<filebuf*>(file.rdbuf()); file.close(); return true; } std::cout << "ERROR" << std::endl; return false; } size_t TextFile::getSize(){ //Evidement ça marche pas... return m_data->str().size(); } void TextFile::destroy(){ std::cout<<"Destroy a textfile" << std::endl; //Evidement ça marche pas... delete (filebuf*)m_data; }
Partager