pool.cpp
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 }