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