Mercurial > hg > svcore
comparison base/MatrixFileCache.cpp @ 93:27d726916ab3
* Remove mmap-based code again. We can be more efficient with read().
author | Chris Cannam |
---|---|
date | Wed, 03 May 2006 16:47:04 +0000 |
parents | 1dcf41ed3863 |
children | 040a151d0897 |
comparison
equal
deleted
inserted
replaced
92:4988de098b25 | 93:27d726916ab3 |
---|---|
28 | 28 |
29 #include <QFileInfo> | 29 #include <QFileInfo> |
30 #include <QFile> | 30 #include <QFile> |
31 #include <QDir> | 31 #include <QDir> |
32 | 32 |
33 //#define HAVE_MMAP 1 | |
34 | |
35 #ifdef HAVE_MMAP | |
36 #include <sys/mman.h> | |
37 #endif | |
38 | |
39 std::map<QString, int> MatrixFileCache::m_refcount; | 33 std::map<QString, int> MatrixFileCache::m_refcount; |
40 QMutex MatrixFileCache::m_refcountMutex; | 34 QMutex MatrixFileCache::m_refcountMutex; |
41 | 35 |
42 //!!! This class is a work in progress -- it does only as much as we | 36 //!!! This class is a work in progress -- it does only as much as we |
43 // need for the current SpectrogramLayer. Slated for substantial | 37 // need for the current SpectrogramLayer. Slated for substantial |
52 m_autoRegionWidth(256), | 46 m_autoRegionWidth(256), |
53 m_off(-1), | 47 m_off(-1), |
54 m_rx(0), | 48 m_rx(0), |
55 m_rw(0), | 49 m_rw(0), |
56 m_userRegion(false), | 50 m_userRegion(false), |
57 m_region(0), | 51 m_region(0) |
58 m_mmapped(false), | |
59 m_mmapSize(0), | |
60 m_mmapOff(0), | |
61 m_preferMmap(false) | |
62 { | 52 { |
63 // Ensure header size is a multiple of the size of our data (for | 53 // Ensure header size is a multiple of the size of our data (for |
64 // alignment purposes) | 54 // alignment purposes) |
65 size_t hs = ((m_headerSize / sizeof(float)) * sizeof(float)); | 55 size_t hs = ((m_headerSize / sizeof(float)) * sizeof(float)); |
66 if (hs != m_headerSize) m_headerSize = hs + sizeof(float); | 56 if (hs != m_headerSize) m_headerSize = hs + sizeof(float); |
119 } | 109 } |
120 | 110 |
121 MatrixFileCache::~MatrixFileCache() | 111 MatrixFileCache::~MatrixFileCache() |
122 { | 112 { |
123 if (m_rw > 0) { | 113 if (m_rw > 0) { |
124 if (m_mmapped) { | 114 delete[] m_region; |
125 #ifdef HAVE_MMAP | |
126 ::munmap(m_region, m_mmapSize); | |
127 #endif | |
128 } else { | |
129 delete[] m_region; | |
130 } | |
131 } | 115 } |
132 | 116 |
133 if (m_fd >= 0) { | 117 if (m_fd >= 0) { |
134 if (::close(m_fd) < 0) { | 118 if (::close(m_fd) < 0) { |
135 ::perror("MatrixFileCache::~MatrixFileCache: close failed"); | 119 ::perror("MatrixFileCache::~MatrixFileCache: close failed"); |
171 | 155 |
172 off_t off = m_headerSize + (w * h * sizeof(float)); | 156 off_t off = m_headerSize + (w * h * sizeof(float)); |
173 | 157 |
174 if (w * h > m_width * m_height) { | 158 if (w * h > m_width * m_height) { |
175 | 159 |
176 #ifdef HAVE_MMAP | 160 /*!!! |
177 // If we're going to mmap the file, we need to ensure it's long | 161 // If we're going to mmap the file, we need to ensure it's long |
178 // enough beforehand | 162 // enough beforehand |
179 | 163 |
180 if (m_preferMmap) { | 164 if (m_preferMmap) { |
181 | 165 |
191 float f(0); | 175 float f(0); |
192 if (::write(m_fd, &f, sizeof(float)) != sizeof(float)) { | 176 if (::write(m_fd, &f, sizeof(float)) != sizeof(float)) { |
193 ::perror("WARNING: MatrixFileCache::resize: write failed"); | 177 ::perror("WARNING: MatrixFileCache::resize: write failed"); |
194 } | 178 } |
195 } | 179 } |
196 #endif | 180 */ |
197 | |
198 } else { | 181 } else { |
199 | 182 |
200 if (::ftruncate(m_fd, off) < 0) { | 183 if (::ftruncate(m_fd, off) < 0) { |
201 ::perror("WARNING: MatrixFileCache::resize: ftruncate failed"); | 184 ::perror("WARNING: MatrixFileCache::resize: ftruncate failed"); |
202 } | 185 } |
356 { | 339 { |
357 if (m_rw == 0) return 0; | 340 if (m_rw == 0) return 0; |
358 | 341 |
359 float *region = m_region; | 342 float *region = m_region; |
360 | 343 |
361 if (m_mmapOff > 0) { | |
362 char *cr = (char *)m_region; | |
363 cr += m_mmapOff; | |
364 region = (float *)cr; | |
365 } | |
366 | |
367 float *ptr = &(region[(x - m_rx) * m_height + y]); | 344 float *ptr = &(region[(x - m_rx) * m_height + y]); |
368 | 345 |
369 // std::cerr << "getRegionPtr(" << x << "," << y << "): region is " << m_region << ", returning " << ptr << std::endl; | 346 // std::cerr << "getRegionPtr(" << x << "," << y << "): region is " << m_region << ", returning " << ptr << std::endl; |
370 return ptr; | 347 return ptr; |
371 } | 348 } |
388 { | 365 { |
389 if (!user && m_userRegion) return false; | 366 if (!user && m_userRegion) return false; |
390 if (m_rw > 0 && x >= m_rx && x + width <= m_rx + m_rw) return true; | 367 if (m_rw > 0 && x >= m_rx && x + width <= m_rx + m_rw) return true; |
391 | 368 |
392 if (m_rw > 0) { | 369 if (m_rw > 0) { |
393 if (m_mmapped) { | 370 delete[] m_region; |
394 #ifdef HAVE_MMAP | |
395 ::munmap(m_region, m_mmapSize); | |
396 std::cerr << "unmapped " << m_mmapSize << " at " << m_region << std::endl; | |
397 #endif | |
398 } else { | |
399 delete[] m_region; | |
400 } | |
401 m_region = 0; | 371 m_region = 0; |
402 m_mmapped = false; | |
403 m_mmapSize = 0; | |
404 m_mmapOff = 0; | |
405 m_rw = 0; | 372 m_rw = 0; |
406 } | 373 } |
407 | 374 |
408 if (width == 0) { | 375 if (width == 0) { |
409 return true; | 376 return true; |
410 } | 377 } |
411 | |
412 #ifdef HAVE_MMAP | |
413 | |
414 if (m_preferMmap) { | |
415 | |
416 size_t mmapSize = m_height * width * sizeof(float); | |
417 off_t offset = m_headerSize + (x * m_height) * sizeof(float); | |
418 int pagesize = getpagesize(); | |
419 off_t aligned = (offset / pagesize) * pagesize; | |
420 size_t mmapOff = offset - aligned; | |
421 mmapSize += mmapOff; | |
422 | |
423 m_region = (float *) | |
424 ::mmap(0, mmapSize, PROT_READ, MAP_PRIVATE, m_fd, aligned); | |
425 | |
426 if (m_region == MAP_FAILED) { | |
427 | |
428 ::perror("Mmap failed"); | |
429 std::cerr << "ERROR: MatrixFileCache::setRegion(" << x << ", " | |
430 << width << "): Mmap(0, " << mmapSize | |
431 << ", " << PROT_READ << ", " << MAP_SHARED << ", " << m_fd | |
432 << ", " << aligned << ") failed, falling back to " | |
433 << "non-mmapping code for this cache" << std::endl; | |
434 m_preferMmap = false; | |
435 | |
436 } else { | |
437 | |
438 std::cerr << "mmap succeeded (offset " << aligned << ", size " << mmapSize << ", m_mmapOff " << mmapOff << ") = " << m_region << std::endl; | |
439 | |
440 m_mmapped = true; | |
441 m_mmapSize = mmapSize; | |
442 m_mmapOff = mmapOff; | |
443 m_rx = x; | |
444 m_rw = width; | |
445 if (user) m_userRegion = true; | |
446 MUNLOCK(m_region, m_mmapSize); | |
447 return true; | |
448 } | |
449 } | |
450 #endif | |
451 | 378 |
452 if (!seekTo(x, 0)) return false; | 379 if (!seekTo(x, 0)) return false; |
453 | 380 |
454 m_region = new float[width * m_height]; | 381 m_region = new float[width * m_height]; |
455 MUNLOCK(m_region, width * m_height * sizeof(float)); | 382 MUNLOCK(m_region, width * m_height * sizeof(float)); |