Mercurial > hg > svcore
comparison base/FileReadThread.cpp @ 95:040a151d0897
* Add file reader thread, and make the matrix file code use it to preload
fft cache data without glitching
author | Chris Cannam |
---|---|
date | Thu, 04 May 2006 13:59:57 +0000 |
parents | |
children | 1aebdc68ec6d |
comparison
equal
deleted
inserted
replaced
94:5b8392e80ed6 | 95:040a151d0897 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "FileReadThread.h" | |
17 | |
18 #include <iostream> | |
19 | |
20 FileReadThread::FileReadThread() : | |
21 m_nextToken(0), | |
22 m_exiting(false) | |
23 { | |
24 } | |
25 | |
26 void | |
27 FileReadThread::run() | |
28 { | |
29 m_mutex.lock(); | |
30 | |
31 while (!m_exiting) { | |
32 if (m_queue.empty()) { | |
33 m_condition.wait(&m_mutex, 1000); | |
34 } else { | |
35 process(); | |
36 notifyCancelled(); | |
37 } | |
38 } | |
39 | |
40 notifyCancelled(); | |
41 m_mutex.unlock(); | |
42 | |
43 std::cerr << "FileReadThread::run() exiting" << std::endl; | |
44 } | |
45 | |
46 void | |
47 FileReadThread::finish() | |
48 { | |
49 std::cerr << "FileReadThread::finish()" << std::endl; | |
50 | |
51 m_mutex.lock(); | |
52 while (!m_queue.empty()) { | |
53 m_cancelledRequests[m_queue.begin()->first] = m_queue.begin()->second; | |
54 m_newlyCancelled.insert(m_queue.begin()->first); | |
55 m_queue.erase(m_queue.begin()); | |
56 } | |
57 | |
58 m_exiting = true; | |
59 m_mutex.unlock(); | |
60 | |
61 m_condition.wakeAll(); | |
62 | |
63 std::cerr << "FileReadThread::finish() exiting" << std::endl; | |
64 } | |
65 | |
66 int | |
67 FileReadThread::request(const Request &request) | |
68 { | |
69 m_mutex.lock(); | |
70 | |
71 int token = m_nextToken++; | |
72 m_queue[token] = request; | |
73 | |
74 m_mutex.unlock(); | |
75 m_condition.wakeAll(); | |
76 | |
77 return token; | |
78 } | |
79 | |
80 void | |
81 FileReadThread::cancel(int token) | |
82 { | |
83 m_mutex.lock(); | |
84 | |
85 if (m_queue.find(token) != m_queue.end()) { | |
86 m_cancelledRequests[token] = m_queue[token]; | |
87 m_queue.erase(token); | |
88 m_newlyCancelled.insert(token); | |
89 } | |
90 | |
91 m_mutex.unlock(); | |
92 } | |
93 | |
94 bool | |
95 FileReadThread::isReady(int token) | |
96 { | |
97 m_mutex.lock(); | |
98 | |
99 bool ready = m_readyRequests.find(token) != m_readyRequests.end(); | |
100 | |
101 m_mutex.unlock(); | |
102 return ready; | |
103 } | |
104 | |
105 bool | |
106 FileReadThread::isCancelled(int token) | |
107 { | |
108 m_mutex.lock(); | |
109 | |
110 bool cancelled = | |
111 m_cancelledRequests.find(token) != m_cancelledRequests.end() && | |
112 m_newlyCancelled.find(token) == m_newlyCancelled.end(); | |
113 | |
114 m_mutex.unlock(); | |
115 return cancelled; | |
116 } | |
117 | |
118 bool | |
119 FileReadThread::getRequest(int token, Request &request) | |
120 { | |
121 m_mutex.lock(); | |
122 | |
123 bool found = false; | |
124 | |
125 if (m_queue.find(token) != m_queue.end()) { | |
126 request = m_queue[token]; | |
127 found = true; | |
128 } else if (m_cancelledRequests.find(token) != m_cancelledRequests.end()) { | |
129 request = m_cancelledRequests[token]; | |
130 found = true; | |
131 } else if (m_readyRequests.find(token) != m_readyRequests.end()) { | |
132 request = m_readyRequests[token]; | |
133 found = true; | |
134 } | |
135 | |
136 m_mutex.unlock(); | |
137 | |
138 return found; | |
139 } | |
140 | |
141 void | |
142 FileReadThread::done(int token) | |
143 { | |
144 m_mutex.lock(); | |
145 | |
146 bool found = false; | |
147 | |
148 if (m_cancelledRequests.find(token) != m_cancelledRequests.end()) { | |
149 m_cancelledRequests.erase(token); | |
150 m_newlyCancelled.erase(token); | |
151 found = true; | |
152 } else if (m_readyRequests.find(token) != m_readyRequests.end()) { | |
153 m_readyRequests.erase(token); | |
154 found = true; | |
155 } else if (m_queue.find(token) != m_queue.end()) { | |
156 std::cerr << "WARNING: FileReadThread::done(" << token << "): request is still in queue (wait or cancel it)" << std::endl; | |
157 } | |
158 | |
159 m_mutex.unlock(); | |
160 | |
161 if (!found) { | |
162 std::cerr << "WARNING: FileReadThread::done(" << token << "): request not found" << std::endl; | |
163 } | |
164 } | |
165 | |
166 void | |
167 FileReadThread::process() | |
168 { | |
169 // entered with m_mutex locked and m_queue non-empty | |
170 | |
171 int token = m_queue.begin()->first; | |
172 Request request = m_queue.begin()->second; | |
173 | |
174 m_mutex.unlock(); | |
175 | |
176 std::cerr << "FileReadThread::process: got something to do" << std::endl; | |
177 | |
178 bool successful = false; | |
179 bool seekFailed = false; | |
180 ssize_t r = 0; | |
181 | |
182 if (request.mutex) request.mutex->lock(); | |
183 | |
184 if (::lseek(request.fd, request.start, SEEK_SET) == (off_t)-1) { | |
185 seekFailed = true; | |
186 } else { | |
187 r = ::read(request.fd, request.data, request.size); | |
188 } | |
189 | |
190 if (request.mutex) request.mutex->unlock(); | |
191 | |
192 if (seekFailed) { | |
193 ::perror("Seek failed"); | |
194 std::cerr << "ERROR: FileReadThread::process: seek to " | |
195 << request.start << " failed" << std::endl; | |
196 request.size = 0; | |
197 } else { | |
198 if (r < 0) { | |
199 ::perror("ERROR: FileReadThread::process: Read failed"); | |
200 request.size = 0; | |
201 } else if (r < ssize_t(request.size)) { | |
202 std::cerr << "WARNING: FileReadThread::process: read " | |
203 << request.size << " returned only " << r << " bytes" | |
204 << std::endl; | |
205 request.size = r; | |
206 } else { | |
207 successful = true; | |
208 } | |
209 } | |
210 | |
211 // Check that the token hasn't been cancelled and the thread | |
212 // hasn't been asked to finish | |
213 | |
214 m_mutex.lock(); | |
215 | |
216 if (m_queue.find(token) != m_queue.end() && !m_exiting) { | |
217 m_queue.erase(token); | |
218 m_readyRequests[token] = request; | |
219 m_mutex.unlock(); | |
220 std::cerr << "emitting" << std::endl; | |
221 emit ready(token, successful); | |
222 m_mutex.lock(); | |
223 } | |
224 } | |
225 | |
226 void | |
227 FileReadThread::notifyCancelled() | |
228 { | |
229 // entered with m_mutex locked | |
230 | |
231 while (!m_newlyCancelled.empty()) { | |
232 int token = *m_newlyCancelled.begin(); | |
233 m_newlyCancelled.erase(token); | |
234 emit cancelled(token); | |
235 } | |
236 } | |
237 | |
238 |