src/hbtools/hbbincssmaker/hbcssconverterutils.cpp
changeset 5 627c4a0fd0e7
parent 2 06ff229162e9
child 7 923ff622b8b9
--- a/src/hbtools/hbbincssmaker/hbcssconverterutils.cpp	Thu May 27 13:10:59 2010 +0300
+++ b/src/hbtools/hbbincssmaker/hbcssconverterutils.cpp	Fri Jun 11 13:58:22 2010 +0300
@@ -55,10 +55,16 @@
     registered.remove(offset);
 }
 
-
-QList<int *> HbCssConverterUtils::registeredOffsetHolders()
+QMultiHash<int, int *> HbCssConverterUtils::registeredOffsetHolders()
 {
-    return registered.keys();
+    QMultiHash<int, int *> holders;
+    holders.reserve(registered.size());
+    QMap<int *, int>::const_iterator end = registered.constEnd();
+    for (QMap<int *, int>::const_iterator i = registered.constBegin(); i != end; ++i) {
+        int *holder = i.key();
+        holders.insertMulti(*holder, holder);
+    }
+    return holders;
 }
 
 void HbCssConverterUtils::unregisterAll()
@@ -84,13 +90,14 @@
         GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
         HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager);
         const char *chunkBase = static_cast<const char *>(shared->base());
+        const char *freedEnd = chunkBase + offset + size;
+        const int *freedStart = reinterpret_cast<const int *>(chunkBase + offset);
 
-        QList<int *> offsetHolders = HbCssConverterUtils::registeredOffsetHolders();
-        for (int i = 0; i<offsetHolders.count(); ++i) {
-            int *holder = offsetHolders.at(i);
-            if ((char*)holder >= chunkBase + offset && (char*)holder < chunkBase + offset + size) {
-                HbCssConverterUtils::unregisterOffsetHolder(holder);
-            }
+        QMap<int *, int>::iterator freedHolders =
+                registered.lowerBound(const_cast<int *>(freedStart));
+        while(freedHolders != registered.end()
+              && reinterpret_cast<char*>(freedHolders.key()) <  freedEnd) {
+            freedHolders = registered.erase(freedHolders);
         }
     }
 }
@@ -102,19 +109,23 @@
     if (size > 0) {
         // Check if there were registered offset holders in the old cell
         // and register corresponding ones in the reallocated cell.
-        QList<int *> holders = HbCssConverterUtils::registeredOffsetHolders();
-
         GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
         HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager);
-        const char *chunkBase = static_cast<const char *>(shared->base());    
-        
-        for (int i=0; i<holders.count(); i++) {
-            int *holder = holders.at(i);
-            char *holderC = (char*)holder;
-            if (holderC >= chunkBase + offset && holderC < chunkBase + offset + size) {
-                HbCssConverterUtils::unregisterOffsetHolder(holder);
-                HbCssConverterUtils::registerOffsetHolder((int*)(holderC + newOffset - offset));
-            }
+        const char *chunkBase = static_cast<const char *>(shared->base());
+        const char *freedEnd = chunkBase + offset + size;
+        const int *freedStart = reinterpret_cast<const int *>(chunkBase + offset);
+
+        QMap<int *, int>::iterator freedHolders =
+                registered.lowerBound(const_cast<int *>(freedStart));
+        QList<int *> newHolders;
+        while(freedHolders != registered.end()
+              && reinterpret_cast<char*>(freedHolders.key()) <  freedEnd) {
+            char *holderC = reinterpret_cast<char*>(freedHolders.key());
+            newHolders.append(reinterpret_cast<int*>(holderC + newOffset - offset));
+            freedHolders = registered.erase(freedHolders);
+        }
+        for (int i = 0; i < newHolders.size(); ++i) {
+            registerOffsetHolder(newHolders.at(i));
         }
     }
 }
@@ -129,62 +140,56 @@
     GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
     HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager);
 
-    // Register shared cache pointer in chunk header as shared cache may also be moved in defragmentation
-    HbSharedChunkHeader *chunkHeader = static_cast<HbSharedChunkHeader*>(shared->base());    
-    HbCssConverterUtils::registerOffsetHolder(reinterpret_cast<int *>(&chunkHeader->sharedCacheOffset));
+    // Register shared cache pointer in chunk header
+    //as shared cache may also be moved in defragmentation
+    HbSharedChunkHeader *chunkHeader = static_cast<HbSharedChunkHeader*>(shared->base());
+    registerOffsetHolder(reinterpret_cast<int *>(&chunkHeader->sharedCacheOffset));
 
-    QList<int *> offsetHolders = HbCssConverterUtils::registeredOffsetHolders();
+    QMultiHash<int, int *> offsetHolders = registeredOffsetHolders();
 
     // Create new buffer where the current chunk contents are defragmented
-    void *buffer = ::malloc(shared->size());
+    char *buffer = static_cast<char*>(::malloc(shared->size()));
     int newCurrentOffset = 0;
 
     // Create new cell order and update offset holders
-    QMap<int,int>::const_iterator i = cells.constBegin();
+    QMap<int,int>::const_iterator end = cells.constEnd();
 
-    while (i != cells.constEnd()) {
+    for (QMap<int,int>::const_iterator i = cells.constBegin(); i != end; ++i) {
         // Get the old cell
         int offset = i.key();
         int size = i.value();
         
         // Update registered offset holders
-
-        // TODO: optimize this, now there's linear search for each cell!
-		for (int j=0; j<offsetHolders.count(); ++j) {
-			int *holder = offsetHolders.at(j);
-			if (*holder == offset) {
-				// Change stored offset value
-				*holder = newCurrentOffset + sizeof(HbSharedChunkHeader);
-			}
-		}
-
+        QList<int *> values = offsetHolders.values(offset);
+        offsetHolders.remove(offset);
+        int newOffset = newCurrentOffset + sizeof(HbSharedChunkHeader);
+        for (int j = 0; j < values.size(); ++j) {
+            int *holder = values[j];
+            *holder = newOffset;
+            offsetHolders.insertMulti(*holder, holder);
+        }
         newCurrentOffset += size;
-        i++;
     }
 
-    i = cells.constBegin();
     newCurrentOffset = 0;
-
     // Move allocated cells to a linear buffer
-    while (i != cells.constEnd()) {
+    for (QMap<int, int>::const_iterator i = cells.constBegin(); i != end; ++i) {
         // Get the old cell
         int offset = i.key();
         int size = i.value();
         // Copy to new chunk
-        memcpy((char*)buffer + newCurrentOffset, (char*)shared->base() + offset, size);
-
+        memcpy(buffer + newCurrentOffset, static_cast<char*>(shared->base()) + offset, size);
         newCurrentOffset += size;
-        i++;
     }
 
     // Free all cells from the shared chunk and move the defragmented buffer in the beginning of the chunk.
     // Note that chunk memory management is screwed up after this point, so no more allocations should be
     // done in it after this.
 
-    HbCssConverterUtils::unregisterAll();
+    unregisterAll();
     QList<int> keys = cells.keys();
 
-    for (int j=0; j<keys.count(); ++j) {
+    for (int j = 0; j < keys.count(); ++j) {
         shared->free(keys.at(j));
     }