00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "util/base/exception.h"
00031 #include "util/log/logger.h"
00032
00033 #include "pool.h"
00034
00035 namespace FIFE {
00036 static Logger _log(LM_POOL);
00037
00038 Pool::Pool(const std::string& name):
00039 m_entries(),
00040 m_location_to_entry(),
00041 m_loaders(),
00042 m_name(name)
00043 {
00044 }
00045
00046 Pool::~Pool() {
00047 FL_LOG(_log, LMsg("Pool destroyed: ") << m_name);
00048 printStatistics();
00049
00050
00051 reset();
00052 std::vector<ResourceLoader*>::iterator loader;
00053 for (loader = m_loaders.begin(); loader != m_loaders.end(); loader++) {
00054 delete (*loader);
00055 }
00056 }
00057
00058 void Pool::reset() {
00059 std::vector<PoolEntry*>::iterator entry;
00060 for (entry = m_entries.begin(); entry != m_entries.end(); entry++) {
00061
00062
00063 if( (*entry)->resource && (*entry)->resource->getRefCount() > 0 ) {
00064 FL_WARN(_log, LMsg(m_name + " leak: ") << (*entry)->location->getFilename());
00065 (*entry)->resource = 0;
00066 }
00067 delete (*entry);
00068 }
00069 m_entries.clear();
00070 m_location_to_entry.clear();
00071 }
00072
00073 int Pool::purgeLoadedResources() {
00074 int count = 0;
00075 std::vector<PoolEntry*>::iterator it;
00076 for (it = m_entries.begin(); it != m_entries.end(); it++) {
00077 PoolEntry* entry = *it;
00078 if( entry->resource && entry->resource->getRefCount() == 0 ) {
00079 delete entry->resource;
00080 entry->resource = 0;
00081 ++count;
00082 }
00083 }
00084 return count;
00085 }
00086
00087 void Pool::addResourceLoader(ResourceLoader* loader) {
00088 m_loaders.push_back(loader);
00089 }
00090
00091 void Pool::clearResourceLoaders() {
00092 m_loaders.clear();
00093 }
00094
00095 int Pool::addResourceFromLocation(ResourceLocation* loc) {
00096 ResourceLocationToEntry::const_iterator it = m_location_to_entry.find(loc);
00097 if (it != m_location_to_entry.end()) {
00098 return it->second;
00099 }
00100
00101 PoolEntry* entry = new PoolEntry();
00102 entry->location = loc->clone();
00103 m_entries.push_back(entry);
00104 size_t index = m_entries.size() - 1;
00105 m_location_to_entry[entry->location] = index;
00106 return index;
00107 }
00108
00109 int Pool::addResourceFromFile(const std::string& filename) {
00110 ResourceLocation r = ResourceLocation(filename);
00111 return addResourceFromLocation(&r);
00112 }
00113
00114 IResource& Pool::get(unsigned int index, bool inc) {
00115 if (index >= m_entries.size()) {
00116 FL_ERR(_log, LMsg("Tried to get with index ") << index << ", only " << m_entries.size() << " items in pool " + m_name);
00117 throw IndexOverflow( __FUNCTION__ );
00118 }
00119 IResource* res = NULL;
00120 PoolEntry* entry = m_entries[index];
00121 if (entry->resource) {
00122 res = entry->resource;
00123 } else {
00124 if (!entry->loader) {
00125 findAndSetProvider(*entry);
00126 } else {
00127 entry->resource = entry->loader->loadResource(*entry->location);
00128 }
00129
00130 if (!entry->loader) {
00131 LMsg msg("No suitable loader was found for resource ");
00132 msg << "#" << index << "<" << entry->location->getFilename()
00133 << "> in pool " << m_name;
00134 FL_ERR(_log, msg);
00135
00136 throw NotFound(msg.str);
00137 }
00138
00139
00140
00141
00142
00143 if (!entry->resource) {
00144 LMsg msg("The loader was unable to load the resource ");
00145 msg << "#" << index << "<" << entry->location->getFilename()
00146 << "> in pool " << m_name;
00147 FL_ERR(_log, msg);
00148 throw NotFound(msg.str);
00149 }
00150 res = entry->resource;
00151 }
00152 if (inc) {
00153 res->addRef();
00154 }
00155 res->setPoolId(index);
00156 return *res;
00157 }
00158
00159 void Pool::release(unsigned int index, bool dec) {
00160 if (index >= m_entries.size()) {
00161 throw IndexOverflow( __FUNCTION__ );
00162 }
00163
00164 IResource* res = NULL;
00165 PoolEntry* entry = m_entries[index];
00166 if (entry->resource) {
00167 res = entry->resource;
00168 if (dec) {
00169 res->decRef();
00170 }
00171 if(res->getRefCount() == 0) {
00172 delete entry->resource;
00173 entry->resource = 0;
00174 }
00175 }
00176 }
00177
00178 int Pool::getResourceCount(int status) {
00179 int amount = 0;
00180 std::vector<PoolEntry*>::iterator entry;
00181 for (entry = m_entries.begin(); entry != m_entries.end(); entry++) {
00182 if (status & RES_LOADED) {
00183 if ((*entry)->resource) {
00184 amount++;
00185 }
00186 }
00187 if (status & RES_NON_LOADED) {
00188 if (!(*entry)->resource) {
00189 amount++;
00190 }
00191 }
00192 }
00193 return amount;
00194 }
00195
00196 void Pool::findAndSetProvider(PoolEntry& entry) {
00197 std::vector<ResourceLoader*>::iterator it = m_loaders.begin();
00198 std::vector<ResourceLoader*>::iterator end = m_loaders.end();
00199 if( it == end ) {
00200 FL_PANIC(_log, "no loader constructors given for resource pool");
00201 }
00202 for(; it != end; ++it) {
00203 IResource* res = (*it)->loadResource(*entry.location);
00204 if (res) {
00205 entry.resource = res;
00206 entry.loader = *it;
00207 return;
00208 }
00209 };
00210 }
00211
00212 void Pool::printStatistics() {
00213 FL_LOG(_log, LMsg("Pool not loaded =") << getResourceCount(RES_NON_LOADED));
00214 FL_LOG(_log, LMsg("Pool loaded =") << getResourceCount(RES_LOADED));
00215 int amount = 0;
00216 std::vector<PoolEntry*>::iterator entry;
00217 for (entry = m_entries.begin(); entry != m_entries.end(); entry++) {
00218 if ((*entry)->resource) {
00219 if ((*entry)->resource->getRefCount() > 0) {
00220 amount++;
00221 }
00222 }
00223 }
00224 FL_LOG(_log, LMsg("Pool locked =") << amount);
00225 FL_LOG(_log, LMsg("Pool total size =") << m_entries.size());
00226 }
00227
00228 void Pool::sanityCheck() {
00229
00230
00231
00232
00233
00234 for(unsigned i = 0; i != m_entries.size(); ++i) {
00235 int count = 0;
00236 for(unsigned j = i+1; j < m_entries.size(); ++j) {
00237 if( *m_entries[i]->location == *m_entries[j]->location )
00238 count ++;
00239 }
00240 if( 0 == count )
00241 continue;
00242 FL_WARN(_log, LMsg("Multiple entries: ") << m_entries[i]->location->getFilename()
00243 << " #entries = " << (count+1) );
00244 }
00245 }
00246
00247 }