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