]> git.tdb.fi Git - libs/gl.git/blob - source/resources/resourcemanager.h
Use default member initializers for simple types
[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 = LOAD_ON_DEMAND;
116         bool async_loads = true;
117         mutable Mutex map_mutex;
118         std::map<const Resource *, ManagedResource> resources;
119         std::deque<ManagedResource *> queue;
120         std::uint64_t total_data_size = 0;
121         std::uint64_t size_limit = 0;
122         unsigned frame = 0;
123         unsigned min_retain_frames = 30;
124         unsigned max_retain_frames = 0;
125         unsigned next_unload = 0;
126         LoadingThread thread;
127
128 public:
129         ~ResourceManager();
130
131         void set_loading_policy(LoadingPolicy);
132         void set_async_loads(bool);
133         void set_size_limit(std::uint64_t);
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         std::uint64_t 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