begin cleaning up resource management
[chaz/yoink] / src / moof / resource.cc
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #include "../config.h"
13
14 #include <queue>
15
16 #ifdef USE_HOTLOADING
17 #include <sys/inotify.h>
18 #include <sys/ioctl.h>
19 #endif
20
21 #include <boost/algorithm/string.hpp>
22 #include <boost/weak_ptr.hpp>
23
24 #include <stlplus/portability/file_system.hpp>
25
26 #include "hash.hh"
27 #include "resource.hh"
28
29
30 #ifndef BUF_SIZE
31 #define BUF_SIZE 4096
32 #endif
33
34
35 namespace moof {
36
37
38 static std::string search_paths_;
39
40 typedef boost::weak_ptr<resource> resource_weakptr;
41 static hash<std::string,resource_weakptr,hash_function> resource_table_;
42
43 // static member
44 resource::type_lookup_ptr resource::type_lookup_;
45
46
47 #ifdef USE_HOTLOADING
48 static hash<int,std::string,hash_function> monitor_lookup_;
49 static int monitor_fd_ = inotify_init1(IN_NONBLOCK);
50 #endif
51
52 int resource::reload_as_needed()
53 {
54 int num_resources = 0;
55
56 #ifdef USE_HOTLOADING
57 log_info("hotloading?");
58 char bytes[BUF_SIZE];
59 int num_bytes;
60 if (0 < (num_bytes = read(monitor_fd_, bytes, num_bytes)))
61 {
62 char* end = bytes + num_bytes;
63 char* byte = bytes;
64
65 log_warning("num_bytes:", num_bytes);
66 log_error("1");
67
68 while (byte < end)
69 {
70 struct inotify_event* event = (struct inotify_event*)byte;
71
72 if (event->mask & IN_IGNORED)
73 {
74 log_warning("watch", event->wd, "removed");
75 }
76
77 log_error("2");
78 hash<int,std::string,hash_function>::iterator it;
79 it = monitor_lookup_.find(event->wd);
80 if (it != monitor_lookup_.end())
81 {
82 log_error("3");
83 std::string path = (*it).second;
84 monitor_lookup_.erase(it);
85 resource::reload(path);
86 }
87
88 byte += sizeof(*event) + event->len;
89
90 ++num_resources;
91 }
92 }
93 #endif
94
95 return num_resources;
96 }
97
98
99 resource::~resource()
100 {
101 #ifdef USE_HOTLOADING
102 inotify_rm_watch(monitor_fd_, wd_);
103 #endif
104 }
105
106
107 resource_ptr resource::load(const std::string& path)
108 {
109 std::string extension = stlplus::extension_part(path);
110
111 if (!find(path)) return resource_ptr();
112
113 hash<std::string,resource_weakptr,hash_function>::iterator it;
114 it = resource_table_.find(path);
115 if (it != resource_table_.end())
116 {
117 resource_weakptr rsrc = (*it).second;
118 resource_ptr locked = rsrc.lock();
119 if (locked) return locked;
120 }
121
122 std::map<std::string,loader_ptr>::iterator jt;
123 jt = type_lookup_->find(extension);
124 if (jt != type_lookup_->end())
125 {
126 resource_ptr rsrc((*jt).second->load(path));
127 rsrc->set_loader(path, (*jt).second);
128 resource_table_[path] = rsrc;
129
130 #ifdef USE_HOTLOADING
131 int wd = inotify_add_watch(monitor_fd_,
132 path.c_str(), IN_MODIFY);
133 rsrc->set_watch_descriptor(wd);
134 monitor_lookup_[wd] = path;
135 #endif
136
137 log_info("loaded", rsrc.get());
138 return rsrc;
139 }
140
141 return resource_ptr();
142 }
143
144
145 resource_ptr resource::reload(std::string& path)
146 {
147 log_info("reloading...", path);
148 hash<std::string,resource_weakptr,hash_function>::iterator it;
149 it = resource_table_.find(path);
150 if (it != resource_table_.end())
151 {
152 resource_weakptr rsrc = (*it).second;
153 resource_ptr locked = rsrc.lock();
154 if (locked)
155 {
156 locked->reload();
157 return locked;
158 }
159 }
160
161 return load(path);
162 }
163
164 void resource::reload()
165 {
166 log_info("reloaded", path_);
167
168 resource* resource = loader_->load(path_);
169 //*this = *resource;
170 resource_ = resource->resource_;
171 typeinfo_ = resource->typeinfo_;
172 unloader_ = resource->unloader_;
173
174 #ifdef USE_HOTLOADING
175 int wd = inotify_add_watch(monitor_fd_,
176 path_.c_str(), IN_MODIFY);
177 set_watch_descriptor(wd);
178 monitor_lookup_[wd] = path_;
179 #endif
180
181 delete resource;
182 }
183
184
185 void resource::add_search_paths(const std::string& paths)
186 {
187 search_paths_ = paths;
188 }
189
190
191 bool resource::find(const std::string& path)
192 {
193 return !stlplus::lookup(path, search_paths_, ":").empty();
194 }
195
196 FILE* resource::open_file(const std::string& path, const std::string& mode)
197 {
198 std::string file = stlplus::lookup(path, search_paths_, ":");
199 return fopen(file.c_str(), mode.c_str());
200 }
201
202
203 } // namespace moof
204
This page took 0.038028 seconds and 4 git commands to generate.