Mercurial > hg > svcore
comparison data/fft/FFTDataServer.cpp @ 215:a051929fef3b
* Attempt to improve management of FFT models that are not currently in use.
I think these are some problems with this at the moment.
author | Chris Cannam |
---|---|
date | Fri, 19 Jan 2007 14:38:57 +0000 |
parents | e0e7f6c5fda9 |
children | 7f8ffe65d453 |
comparison
equal
deleted
inserted
replaced
214:ce6f65ab3327 | 215:a051929fef3b |
---|---|
38 #define DEBUG_FFT_SERVER 1 | 38 #define DEBUG_FFT_SERVER 1 |
39 #endif | 39 #endif |
40 #endif | 40 #endif |
41 | 41 |
42 FFTDataServer::ServerMap FFTDataServer::m_servers; | 42 FFTDataServer::ServerMap FFTDataServer::m_servers; |
43 FFTDataServer::ServerQueue FFTDataServer::m_releasedServers; | |
43 QMutex FFTDataServer::m_serverMapMutex; | 44 QMutex FFTDataServer::m_serverMapMutex; |
44 | 45 |
45 FFTDataServer * | 46 FFTDataServer * |
46 FFTDataServer::getInstance(const DenseTimeValueModel *model, | 47 FFTDataServer::getInstance(const DenseTimeValueModel *model, |
47 int channel, | 48 int channel, |
231 | 232 |
232 QMutexLocker locker(&m_serverMapMutex); | 233 QMutexLocker locker(&m_serverMapMutex); |
233 | 234 |
234 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { | 235 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { |
235 if (i->second.first == server) { | 236 if (i->second.first == server) { |
237 | |
238 for (ServerQueue::iterator j = m_releasedServers.begin(); | |
239 j != m_releasedServers.end(); ++j) { | |
240 if (*j == server) { | |
241 m_releasedServers.erase(j); | |
242 break; | |
243 } | |
244 } | |
245 | |
236 ++i->second.second; | 246 ++i->second.second; |
237 return; | 247 return; |
238 } | 248 } |
239 } | 249 } |
240 | 250 |
248 #ifdef DEBUG_FFT_SERVER | 258 #ifdef DEBUG_FFT_SERVER |
249 std::cerr << "FFTDataServer::releaseInstance(" << server << ")" << std::endl; | 259 std::cerr << "FFTDataServer::releaseInstance(" << server << ")" << std::endl; |
250 #endif | 260 #endif |
251 | 261 |
252 QMutexLocker locker(&m_serverMapMutex); | 262 QMutexLocker locker(&m_serverMapMutex); |
253 | |
254 //!!! not a good strategy. Want something like: | |
255 | 263 |
256 // -- if ref count > 0, decrement and return | 264 // -- if ref count > 0, decrement and return |
257 // -- if the instance hasn't been used at all, delete it immediately | 265 // -- if the instance hasn't been used at all, delete it immediately |
258 // -- if fewer than N instances (N = e.g. 3) remain with zero refcounts, | 266 // -- if fewer than N instances (N = e.g. 3) remain with zero refcounts, |
259 // leave them hanging around | 267 // leave them hanging around |
262 // -- if we run out of disk space when allocating an instance, go back | 270 // -- if we run out of disk space when allocating an instance, go back |
263 // and delete the spare N instances before trying again | 271 // and delete the spare N instances before trying again |
264 // -- have an additional method to indicate that a model has been | 272 // -- have an additional method to indicate that a model has been |
265 // destroyed, so that we can delete all of its fft server instances | 273 // destroyed, so that we can delete all of its fft server instances |
266 | 274 |
267 // also: | |
268 // | |
269 | |
270 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { | 275 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { |
271 if (i->second.first == server) { | 276 if (i->second.first == server) { |
272 if (i->second.second == 0) { | 277 if (i->second.second == 0) { |
273 std::cerr << "ERROR: FFTDataServer::releaseInstance(" | 278 std::cerr << "ERROR: FFTDataServer::releaseInstance(" |
274 << server << "): instance not allocated" << std::endl; | 279 << server << "): instance not allocated" << std::endl; |
275 } else if (--i->second.second == 0) { | 280 } else if (--i->second.second == 0) { |
276 if (server->m_lastUsedCache == -1) { // never used | 281 if (server->m_lastUsedCache == -1) { // never used |
277 delete server; | 282 delete server; |
278 m_servers.erase(i); | 283 m_servers.erase(i); |
279 } else { | 284 } else { |
285 m_releasedServers.push_back(server); | |
280 server->suspend(); | 286 server->suspend(); |
281 purgeLimbo(); | 287 purgeLimbo(); |
282 } | 288 } |
283 } | 289 } |
284 return; | 290 return; |
290 } | 296 } |
291 | 297 |
292 void | 298 void |
293 FFTDataServer::purgeLimbo(int maxSize) | 299 FFTDataServer::purgeLimbo(int maxSize) |
294 { | 300 { |
295 ServerMap::iterator i = m_servers.end(); | 301 while (m_releasedServers.size() > maxSize) { |
296 | 302 |
297 int count = 0; | 303 FFTDataServer *server = *m_releasedServers.begin(); |
298 | 304 |
299 while (i != m_servers.begin()) { | 305 bool found = false; |
300 --i; | 306 |
301 if (i->second.second == 0) { | 307 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { |
302 if (++count > maxSize) { | 308 |
303 delete i->second.first; | 309 if (i->second.first == server) { |
310 found = true; | |
311 if (i->second.second > 0) { | |
312 std::cerr << "ERROR: FFTDataServer::purgeLimbo: Server " | |
313 << server << " is in released queue, but still has non-zero refcount " | |
314 << i->second.second << std::endl; | |
315 // ... so don't delete it | |
316 break; | |
317 } | |
304 m_servers.erase(i); | 318 m_servers.erase(i); |
305 return; | 319 delete server; |
306 } | 320 break; |
321 } | |
322 } | |
323 | |
324 if (!found) { | |
325 std::cerr << "ERROR: FFTDataServer::purgeLimbo: Server " | |
326 << server << " is in released queue, but not in server map!" | |
327 << std::endl; | |
328 delete server; | |
329 } | |
330 | |
331 m_releasedServers.pop_front(); | |
332 } | |
333 } | |
334 | |
335 void | |
336 FFTDataServer::modelAboutToBeDeleted(Model *model) | |
337 { | |
338 QMutexLocker locker(&m_serverMapMutex); | |
339 | |
340 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { | |
341 | |
342 FFTDataServer *server = i->second.first; | |
343 | |
344 if (server->getModel() == model) { | |
345 if (i->second.second > 0) { | |
346 std::cerr << "ERROR: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName().toStdString() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << std::endl; | |
347 } | |
348 for (ServerQueue::iterator j = m_releasedServers.begin(); | |
349 j != m_releasedServers.end(); ++j) { | |
350 if (*j == server) { | |
351 m_releasedServers.erase(j); | |
352 break; | |
353 } | |
354 } | |
355 m_servers.erase(i); | |
356 delete server; | |
357 return; | |
307 } | 358 } |
308 } | 359 } |
309 } | 360 } |
310 | 361 |
311 FFTDataServer::FFTDataServer(QString fileBaseName, | 362 FFTDataServer::FFTDataServer(QString fileBaseName, |
372 } | 423 } |
373 | 424 |
374 int cells = m_width * m_height; | 425 int cells = m_width * m_height; |
375 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb | 426 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb |
376 int maximumSize = (cells / 1024) * sizeof(float); // kb | 427 int maximumSize = (cells / 1024) * sizeof(float); // kb |
377 | |
378 // This can throw InsufficientDiscSpace. We don't catch it here -- we | |
379 // haven't allocated anything yet and can safely let the exception out. | |
380 // Caller needs to check for it. | |
381 | 428 |
382 StorageAdviser::Recommendation recommendation = | 429 StorageAdviser::Recommendation recommendation; |
383 StorageAdviser::recommend(criteria, minimumSize, maximumSize); | 430 |
431 try { | |
432 | |
433 recommendation = | |
434 StorageAdviser::recommend(criteria, minimumSize, maximumSize); | |
435 | |
436 } catch (InsufficientDiscSpace s) { | |
437 | |
438 // Delete any unused servers we may have been leaving around | |
439 // in case we wanted them again | |
440 | |
441 purgeLimbo(0); | |
442 | |
443 // This time we don't catch InsufficientDiscSpace -- we | |
444 // haven't allocated anything yet and can safely let the | |
445 // exception out to indicate to the caller that we can't | |
446 // handle it. | |
447 | |
448 recommendation = | |
449 StorageAdviser::recommend(criteria, minimumSize, maximumSize); | |
450 } | |
384 | 451 |
385 std::cerr << "Recommendation was: " << recommendation << std::endl; | 452 std::cerr << "Recommendation was: " << recommendation << std::endl; |
386 | 453 |
387 m_memoryCache = ((recommendation & StorageAdviser::UseMemory) || | 454 m_memoryCache = ((recommendation & StorageAdviser::UseMemory) || |
388 (recommendation & StorageAdviser::PreferMemory)); | 455 (recommendation & StorageAdviser::PreferMemory)); |