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");
84 managed.start_loading();
87 queue.push_back(&managed);
90 while(!managed.loader->process()) ;
91 managed.finish_loading();
95 void ResourceManager::resource_used(const Resource &r)
97 ManagedResource *managed = reinterpret_cast<ManagedResource *>(r.get_manager_data());
98 if(!managed->loaded && !managed->loader && policy!=LOAD_MANUALLY)
99 load_resource(*managed->resource);
101 managed->last_used = frame;
102 if(max_retain_frames && !next_unload)
103 next_unload = frame+max_retain_frames;
106 void ResourceManager::remove_resource(Resource &r)
108 ManagedResource *loading = thread.get_resource();
109 if(loading && loading->resource==&r)
110 thread.set_resource(0);
112 remove_existing(resources, &r);
115 void ResourceManager::watch_resource(const Resource &r, ResourceWatcher &w)
117 get_item(resources, &r).add_watcher(w);
120 void ResourceManager::unwatch_resource(const Resource &r, ResourceWatcher &w)
122 get_item(resources, &r).remove_watcher(w);
125 void ResourceManager::tick()
127 LoadingThread::State thread_state = thread.get_state();
128 bool check_total_size = false;
129 if(thread_state==LoadingThread::SYNC_PENDING || thread_state==LoadingThread::LOAD_FINISHED)
132 check_total_size = true;
134 else if(thread_state==LoadingThread::IDLE && !queue.empty())
136 ManagedResource *managed = queue.front();
138 thread.set_resource(managed);
142 if(frame==next_unload)
144 unsigned unload_limit = frame-max_retain_frames;
147 for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
150 if(i->second.last_used<=unload_limit)
152 else if(!next_unload || i->second.last_used<next_unload)
153 next_unload = i->second.last_used;
157 next_unload += max_retain_frames;
162 while(get_total_data_size()>size_limit)
164 unsigned unload_limit = frame-min_retain_frames;
165 ManagedResource *best = 0;
166 UInt64 best_impact = 0;
167 for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
168 if(i->second.loaded && i->second.last_used<unload_limit)
170 UInt64 impact = i->second.data_size*(frame-i->second.last_used);
171 if(!best || impact>best_impact)
174 best_impact = impact;
186 UInt64 ResourceManager::get_total_data_size() const
189 for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i)
191 total += i->second.data_size;
196 ResourceManager::ManagedResource::ManagedResource(Resource &r):
206 void ResourceManager::ManagedResource::start_loading()
208 io = collection->open_raw(name);
209 loader = resource->load(*io);
214 throw logic_error("no loader created");
218 void ResourceManager::ManagedResource::finish_loading()
225 data_size = resource->get_data_size();
227 for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
228 (*i)->resource_loaded(*resource);
231 void ResourceManager::ManagedResource::unload()
236 for(vector<ResourceWatcher *>::const_iterator i=watchers.begin(); i!=watchers.end(); ++i)
237 (*i)->resource_unloaded(*resource);
240 void ResourceManager::ManagedResource::add_watcher(ResourceWatcher &w)
242 if(find(watchers.begin(), watchers.end(), &w)==watchers.end())
243 watchers.push_back(&w);
246 void ResourceManager::ManagedResource::remove_watcher(ResourceWatcher &w)
248 vector<ResourceWatcher *>::iterator end = remove(watchers.begin(), watchers.end(), &w);
249 if(end!=watchers.end())
250 watchers.erase(end, watchers.end());
254 ResourceManager::LoadingThread::LoadingThread(ResourceManager &m):
263 void ResourceManager::LoadingThread::main()
265 while(state!=TERMINATING)
271 Resource::AsyncLoader *ldr = resource->loader;
272 bool finished = false;
273 while(!finished && !ldr->needs_sync())
274 finished = ldr->process();
277 state = LOAD_FINISHED;
279 state = SYNC_PENDING;
284 void ResourceManager::LoadingThread::set_resource(ManagedResource *r)
289 // Force finish to clean up the loader
290 state = LOAD_FINISHED;
299 void ResourceManager::LoadingThread::sync()
302 bool finished = (s==LOAD_FINISHED);
305 Resource::AsyncLoader *ldr = resource->loader;
306 while(!finished && ldr->needs_sync())
307 finished = ldr->process();
319 resource->finish_loading();
325 void ResourceManager::LoadingThread::terminate()