2 #include <msp/time/utils.h>
3 #include "resourcemanager.h"
4 #include "resourcewatcher.h"
11 ResourceManager::ResourceManager():
12 policy(LOAD_ON_DEMAND),
16 min_retain_frames(30),
22 ResourceManager::~ResourceManager()
26 while(!resources.empty())
27 resources.begin()->second.resource->set_manager(0);
30 void ResourceManager::set_loading_policy(LoadingPolicy p)
35 void ResourceManager::set_async_loads(bool a)
40 void ResourceManager::set_size_limit(UInt64 s)
45 void ResourceManager::set_min_retain_frames(unsigned f)
47 min_retain_frames = f;
50 void ResourceManager::set_max_retain_frames(unsigned f)
52 max_retain_frames = f;
55 void ResourceManager::add_resource(Resource &r)
57 insert_unique(resources, &r, ManagedResource(r));
60 void *ResourceManager::get_data_for_resource(const Resource &r)
62 return &get_item(resources, &r);
65 void ResourceManager::set_resource_location(Resource &r, DataFile::Collection &c, const string &n)
67 ManagedResource &managed = get_item(resources, &r);
68 managed.collection = &c;
71 if(policy==LOAD_IMMEDIATELY)
75 void ResourceManager::load_resource(Resource &r)
77 ManagedResource &managed = get_item(resources, &r);
78 if(!managed.collection)
79 throw runtime_error("no location");
81 if(managed.state!=ManagedResource::NOT_LOADED)
86 managed.state = ManagedResource::LOAD_QUEUED;
87 queue.push_back(&managed);
91 managed.start_loading();
92 while(!managed.loader->process()) ;
93 managed.finish_loading();
97 void ResourceManager::resource_used(const Resource &r)
99 ManagedResource *managed = reinterpret_cast<ManagedResource *>(r.get_manager_data());
100 if(managed->state==ManagedResource::NOT_LOADED && policy!=LOAD_MANUALLY)
101 load_resource(*managed->resource);
103 managed->last_used = frame;
104 if(max_retain_frames && !next_unload)
105 next_unload = frame+max_retain_frames;
108 void ResourceManager::remove_resource(Resource &r)
110 ManagedResource *loading = thread.get_resource();
111 if(loading && loading->resource==&r)
112 thread.set_resource(0);
114 remove_existing(resources, &r);
117 void ResourceManager::watch_resource(const Resource &r, ResourceWatcher &w)
119 get_item(resources, &r).add_watcher(w);
122 void ResourceManager::unwatch_resource(const Resource &r, ResourceWatcher &w)
124 get_item(resources, &r).remove_watcher(w);
127 void ResourceManager::tick()
129 LoadingThread::State thread_state = thread.get_state();
130 bool check_total_size = false;
131 if(thread_state==LoadingThread::SYNC_PENDING || thread_state==LoadingThread::LOAD_FINISHED)
134 check_total_size = true;
136 else if(thread_state==LoadingThread::IDLE && !queue.empty())
138 ManagedResource *managed = queue.front();
140 thread.set_resource(managed);
144 if(frame==next_unload)
146 unsigned unload_limit = frame-max_retain_frames;
149 for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
150 if(i->second.state==ManagedResource::LOADED)
152 if(i->second.last_used<=unload_limit)
154 else if(!next_unload || i->second.last_used<next_unload)
155 next_unload = i->second.last_used;
159 next_unload += max_retain_frames;
164 while(get_total_data_size()>size_limit)
166 unsigned unload_limit = frame-min_retain_frames;
167 ManagedResource *best = 0;
168 UInt64 best_impact = 0;
169 for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
170 if(i->second.state==ManagedResource::LOADED && i->second.last_used<unload_limit)
172 UInt64 impact = i->second.data_size*(frame-i->second.last_used);
173 if(!best || impact>best_impact)
176 best_impact = impact;
188 UInt64 ResourceManager::get_total_data_size() const
191 for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i)
192 if(i->second.state==ManagedResource::LOADED)
193 total += i->second.data_size;
198 ResourceManager::ManagedResource::ManagedResource(Resource &r):
208 void ResourceManager::ManagedResource::start_loading()
210 io = collection->open_raw(name);
211 loader = resource->load(*io);
216 throw logic_error("no loader created");
221 void ResourceManager::ManagedResource::finish_loading()
228 data_size = resource->get_data_size();
230 for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
231 (*i)->resource_loaded(*resource);
234 void ResourceManager::ManagedResource::unload()
239 for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
240 (*i)->resource_unloaded(*resource);
243 void ResourceManager::ManagedResource::add_watcher(ResourceWatcher &w)
245 if(find(watchers.begin(), watchers.end(), &w)==watchers.end())
246 watchers.push_back(&w);
249 void ResourceManager::ManagedResource::remove_watcher(ResourceWatcher &w)
251 vector<ResourceWatcher *>::iterator end = remove(watchers.begin(), watchers.end(), &w);
252 if(end!=watchers.end())
253 watchers.erase(end, watchers.end());
257 ResourceManager::LoadingThread::LoadingThread(ResourceManager &m):
266 void ResourceManager::LoadingThread::main()
268 while(state!=TERMINATING)
274 Resource::AsyncLoader *ldr = resource->loader;
275 bool finished = false;
276 while(!finished && !ldr->needs_sync())
277 finished = ldr->process();
280 state = LOAD_FINISHED;
282 state = SYNC_PENDING;
287 void ResourceManager::LoadingThread::set_resource(ManagedResource *r)
292 // Force finish to clean up the loader
293 state = LOAD_FINISHED;
298 resource->start_loading();
303 void ResourceManager::LoadingThread::sync()
306 bool finished = (s==LOAD_FINISHED);
309 Resource::AsyncLoader *ldr = resource->loader;
310 while(!finished && ldr->needs_sync())
311 finished = ldr->process();
323 resource->finish_loading();
329 void ResourceManager::LoadingThread::terminate()