1 #include <msp/time/utils.h>
2 #include "resourcemanager.h"
9 ResourceManager::ResourceManager():
10 policy(LOAD_ON_DEMAND),
14 min_retain_frames(30),
20 ResourceManager::~ResourceManager()
24 for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
25 i->second.resource->set_manager(0);
28 void ResourceManager::set_loading_policy(LoadingPolicy p)
33 void ResourceManager::set_async_loads(bool a)
38 void ResourceManager::set_size_limit(UInt64 s)
43 void ResourceManager::set_min_retain_frames(unsigned f)
45 min_retain_frames = f;
48 void ResourceManager::set_max_retain_frames(unsigned f)
50 max_retain_frames = f;
53 void ResourceManager::add_resource(Resource &r)
55 insert_unique(resources, &r, ManagedResource(r));
58 void *ResourceManager::get_data_for_resource(const Resource &r)
60 return &get_item(resources, &r);
63 void ResourceManager::set_resource_location(Resource &r, DataFile::Collection &c, const string &n)
65 ManagedResource &managed = get_item(resources, &r);
66 managed.collection = &c;
69 if(policy==LOAD_IMMEDIATELY)
73 void ResourceManager::load_resource(Resource &r)
75 ManagedResource &managed = get_item(resources, &r);
76 if(!managed.collection)
77 throw runtime_error("no location");
82 managed.start_loading();
85 queue.push_back(&managed);
88 while(!managed.loader->process()) ;
89 managed.finish_loading();
93 void ResourceManager::resource_used(const Resource &r)
95 ManagedResource *managed = reinterpret_cast<ManagedResource *>(r.get_manager_data());
96 if(!managed->loaded && !managed->loader && policy!=LOAD_MANUALLY)
97 load_resource(*managed->resource);
99 managed->last_used = frame;
100 if(max_retain_frames && !next_unload)
101 next_unload = frame+max_retain_frames;
104 void ResourceManager::remove_resource(Resource &r)
106 ManagedResource *loading = thread.get_resource();
107 if(loading && loading->resource==&r)
108 thread.set_resource(0);
110 remove_existing(resources, &r);
113 void ResourceManager::tick()
115 LoadingThread::State thread_state = thread.get_state();
116 bool check_total_size = false;
117 if(thread_state==LoadingThread::SYNC_PENDING)
120 check_total_size = true;
122 else if(thread_state==LoadingThread::IDLE && !queue.empty())
124 ManagedResource *managed = queue.front();
126 thread.set_resource(managed);
130 if(frame==next_unload)
132 unsigned unload_limit = frame-max_retain_frames;
135 for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
138 if(i->second.last_used<=unload_limit)
140 else if(!next_unload || i->second.last_used<next_unload)
141 next_unload = i->second.last_used;
145 next_unload += max_retain_frames;
150 while(get_total_data_size()>size_limit)
152 unsigned unload_limit = frame-min_retain_frames;
153 ManagedResource *best = 0;
154 UInt64 best_impact = 0;
155 for(ResourceMap::iterator i=resources.begin(); i!=resources.end(); ++i)
156 if(i->second.loaded && i->second.last_used<unload_limit)
158 UInt64 impact = i->second.data_size*(frame-i->second.last_used);
159 if(!best || impact<best_impact)
162 best_impact = impact;
174 UInt64 ResourceManager::get_total_data_size() const
177 for(ResourceMap::const_iterator i=resources.begin(); i!=resources.end(); ++i)
179 total += i->second.data_size;
184 ResourceManager::ManagedResource::ManagedResource(Resource &r):
194 void ResourceManager::ManagedResource::start_loading()
196 io = collection->open_raw(name);
197 loader = resource->load(*io);
202 throw logic_error("no loader created");
206 void ResourceManager::ManagedResource::finish_loading()
213 data_size = resource->get_data_size();
216 void ResourceManager::ManagedResource::unload()
223 ResourceManager::LoadingThread::LoadingThread(ResourceManager &m):
232 void ResourceManager::LoadingThread::main()
234 while(state!=TERMINATING)
240 Resource::AsyncLoader *ldr = resource->loader;
241 bool finished = false;
242 while(!finished && !ldr->needs_sync())
243 finished = ldr->process();
246 state = LOAD_FINISHED;
248 state = SYNC_PENDING;
253 void ResourceManager::LoadingThread::set_resource(ManagedResource *r)
258 // Force finish to clean up the loader
259 state = LOAD_FINISHED;
268 void ResourceManager::LoadingThread::sync()
271 bool finished = (s==LOAD_FINISHED);
274 Resource::AsyncLoader *ldr = resource->loader;
275 while(!finished && ldr->needs_sync())
276 finished = ldr->process();
288 resource->finish_loading();
294 void ResourceManager::LoadingThread::terminate()