]> git.tdb.fi Git - libs/gl.git/blob - source/resources/resourcemanager.h
Use C++11 features with containers
[libs/gl.git] / source / resources / resourcemanager.h
1 #ifndef MSP_GL_RESOURCEMANAGER_H_
2 #define MSP_GL_RESOURCEMANAGER_H_
3
4 #include <msp/core/inttypes.h>
5 #include <msp/core/mutex.h>
6 #include <msp/core/semaphore.h>
7 #include <msp/core/thread.h>
8 #include <msp/datafile/collection.h>
9 #include "resource.h"
10
11 namespace Msp {
12 namespace GL {
13
14 class ResourceObserver;
15
16 class resource_load_error: public std::runtime_error
17 {
18 public:
19         resource_load_error(const std::string &, const std::string &);
20         resource_load_error(const std::string &, const std::exception &);
21         virtual ~resource_load_error() throw() { }
22 };
23
24
25 class ResourceManager
26 {
27 public:
28         enum LoadingPolicy
29         {
30                 LOAD_IMMEDIATELY,
31                 LOAD_ON_DEMAND,
32                 LOAD_MANUALLY
33         };
34
35         struct ResourceLocation
36         {
37                 DataFile::Collection *collection;
38                 std::string name;
39
40                 ResourceLocation();
41                 ResourceLocation(DataFile::Collection &, const std::string &);
42         };
43
44 private:
45         struct ManagedResource
46         {
47                 enum State
48                 {
49                         NOT_LOADED,
50                         LOAD_QUEUED,
51                         LOADING,
52                         LOAD_FINISHED,
53                         LOADED,
54                         LOAD_ERROR
55                 };
56
57                 Resource *resource;
58                 ResourceLocation location;
59                 int load_priority;
60                 IO::Seekable *io;
61                 Resource::AsyncLoader *loader;
62                 State state;
63                 unsigned last_used;
64                 UInt64 data_size;
65                 std::vector<ResourceObserver *> observers;
66
67                 ManagedResource(Resource &);
68
69                 void start_loading();
70                 bool process(bool);
71                 void finish_loading(bool);
72                 void finish_loading();
73                 void unload();
74
75                 void add_observer(ResourceObserver &);
76                 void remove_observer(ResourceObserver &);
77         };
78
79         class LoadingThread: public Thread
80         {
81         private:
82                 Semaphore sem;
83                 Mutex queue_mutex;
84                 std::list<ManagedResource *> async_queue;
85                 std::list<ManagedResource *> sync_queue;
86                 unsigned capacity;
87                 unsigned size;
88                 std::list<resource_load_error> error_queue;
89                 Mutex data_size_mutex;
90                 UInt64 loaded_data_size;
91                 volatile bool done;
92
93         public:
94                 LoadingThread();
95
96         private:
97                 virtual void main();
98
99                 ManagedResource *front(std::list<ManagedResource *> &);
100
101         public:
102                 void add_resource(ManagedResource &);
103                 void remove_resource(ManagedResource &);
104         private:
105                 bool try_remove_resource(ManagedResource &);
106         public:
107                 bool sync();
108                 bool needs_work() const { return size<capacity; }
109                 UInt64 get_and_reset_loaded_data_size();
110
111                 void terminate();
112         };
113
114         LoadingPolicy policy;
115         bool async_loads;
116         mutable Mutex map_mutex;
117         std::map<const Resource *, ManagedResource> resources;
118         std::list<ManagedResource *> queue;
119         UInt64 total_data_size;
120         UInt64 size_limit;
121         unsigned frame;
122         unsigned min_retain_frames;
123         unsigned max_retain_frames;
124         unsigned next_unload;
125         LoadingThread thread;
126
127 public:
128         ResourceManager();
129         ~ResourceManager();
130
131         void set_loading_policy(LoadingPolicy);
132         void set_async_loads(bool);
133         void set_size_limit(UInt64);
134         void set_min_retain_frames(unsigned);
135         void set_max_retain_frames(unsigned);
136
137         void add_resource(Resource &);
138 private:
139         const ManagedResource &get_managed_resource(const Resource &) const;
140         ManagedResource &get_managed_resource(const Resource &);
141 public:
142         void *get_data_for_resource(const Resource &r) { return &get_managed_resource(r); }
143         void set_resource_location(Resource &, DataFile::Collection &, const std::string &);
144         void set_resource_location(Resource &, const ResourceLocation &);
145         const ResourceLocation *get_resource_location(const Resource &) const;
146         void load_resource(Resource &);
147         bool is_resource_loaded(const Resource &) const;
148         void resource_used(const Resource &);
149         void remove_resource(Resource &);
150
151         void observe_resource(const Resource &, ResourceObserver &);
152         void unobserve_resource(const Resource &, ResourceObserver &);
153
154         void tick();
155 private:
156         void dispatch_work();
157         void unload_by_age();
158         void unload_by_size();
159 public:
160         UInt64 get_total_data_size() const { return total_data_size; }
161
162 private:
163         static bool age_order(ManagedResource *, ManagedResource *);
164 };
165
166 } // namespace GL
167 } // namespace Msp
168
169 #endif