]> git.tdb.fi Git - libs/gl.git/blob - source/resourcemanager.h
Throw a resource_load_error if the source could not be opened
[libs/gl.git] / source / 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 ResourceWatcher;
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                 IO::Seekable *io;
60                 Resource::AsyncLoader *loader;
61                 State state;
62                 unsigned last_used;
63                 UInt64 data_size;
64                 std::vector<ResourceWatcher *> watchers;
65
66                 ManagedResource(Resource &);
67
68                 void start_loading();
69                 bool process(bool);
70                 void finish_loading(bool);
71                 void finish_loading();
72                 void unload();
73
74                 void add_watcher(ResourceWatcher &);
75                 void remove_watcher(ResourceWatcher &);
76         };
77
78         typedef std::list<ManagedResource *> LoadQueue;
79
80         class LoadingThread: public Thread
81         {
82         private:
83                 Semaphore sem;
84                 Mutex queue_mutex;
85                 LoadQueue async_queue;
86                 LoadQueue sync_queue;
87                 unsigned capacity;
88                 unsigned size;
89                 std::list<resource_load_error> error_queue;
90                 volatile bool done;
91
92         public:
93                 LoadingThread();
94
95         private:
96                 virtual void main();
97
98                 ManagedResource *front(LoadQueue &);
99
100         public:
101                 void add_resource(ManagedResource &);
102                 void remove_resource(ManagedResource &);
103         private:
104                 bool try_remove_resource(ManagedResource &);
105         public:
106                 bool sync();
107                 bool needs_work() const { return size<capacity; }
108
109                 void terminate();
110         };
111
112         typedef std::map<const Resource *, ManagedResource> ResourceMap;
113
114         LoadingPolicy policy;
115         bool async_loads;
116         ResourceMap resources;
117         LoadQueue queue;
118         UInt64 size_limit;
119         unsigned frame;
120         unsigned min_retain_frames;
121         unsigned max_retain_frames;
122         unsigned next_unload;
123         LoadingThread thread;
124
125 public:
126         ResourceManager();
127         ~ResourceManager();
128
129         void set_loading_policy(LoadingPolicy);
130         void set_async_loads(bool);
131         void set_size_limit(UInt64);
132         void set_min_retain_frames(unsigned);
133         void set_max_retain_frames(unsigned);
134
135         void add_resource(Resource &);
136         void *get_data_for_resource(const Resource &);
137         void set_resource_location(Resource &, DataFile::Collection &, const std::string &);
138         void set_resource_location(Resource &, const ResourceLocation &);
139         const ResourceLocation *get_resource_location(const Resource &) const;
140         void load_resource(Resource &);
141         bool is_resource_loaded(const Resource &) const;
142         void resource_used(const Resource &);
143         void remove_resource(Resource &);
144
145         void watch_resource(const Resource &, ResourceWatcher &);
146         void unwatch_resource(const Resource &, ResourceWatcher &);
147
148         void tick();
149 private:
150         void dispatch_work();
151         void unload_by_age();
152         void unload_by_size();
153 public:
154         UInt64 get_total_data_size() const;
155
156 private:
157         static bool age_order(ManagedResource *, ManagedResource *);
158 };
159
160 } // namespace GL
161 } // namespace Msp
162
163 #endif