Changeset 44193 in vbox for trunk/src/VBox/GuestHost
- Timestamp:
- Dec 20, 2012 11:34:25 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/OpenGL/util/hash.c
r44125 r44193 10 10 #include "cr_error.h" 11 11 12 #include <iprt/list.h> 13 12 14 #define CR_MAXUINT ((GLuint) 0xFFFFFFFF) 15 #define CR_HASH_ID_MIN ((GLuint)1) 16 #define CR_HASH_ID_MAX CR_MAXUINT 13 17 14 18 #define CR_NUM_BUCKETS 1047 15 19 16 20 typedef struct FreeElemRec { 21 RTLISTNODE Node; 17 22 GLuint min; 18 23 GLuint max; 19 struct FreeElemRec *next;20 struct FreeElemRec *prev;21 24 } FreeElem; 22 25 23 26 typedef struct CRHashIdPoolRec { 24 FreeElem *freeList;27 RTLISTNODE freeList; 25 28 } CRHashIdPool; 26 29 … … 44 47 { 45 48 CRHashIdPool *pool = (CRHashIdPool *) crCalloc(sizeof(CRHashIdPool)); 46 pool->freeList= (FreeElem *) crCalloc(sizeof(FreeElem));47 pool->freeList->min = 1;48 pool->freeList->max = CR_MAXUINT;49 pool->freeList->next = NULL;50 pool->freeList->prev = NULL;49 FreeElem *elem = (FreeElem *) crCalloc(sizeof(FreeElem)); 50 RTListInit(&pool->freeList); 51 elem->min = CR_HASH_ID_MIN; 52 elem->max = CR_HASH_ID_MAX; 53 RTListAppend(&pool->freeList, &elem->Node); 51 54 return pool; 52 55 } … … 55 58 { 56 59 FreeElem *i, *next; 57 for (i = pool->freeList; i; i = next) 58 { 59 next = i->next; 60 RTListForEachSafe(&pool->freeList, i, next, FreeElem, Node) 61 { 60 62 crFree(i); 61 63 } 64 62 65 crFree(pool); 63 66 } 67 68 static GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id ); 69 70 #ifdef DEBUG_misha 71 static void crHashIdPoolDbgCheckConsistency(CRHashIdPool *pool) 72 { 73 FreeElem *i; 74 GLuint min = 0; 75 76 /* null is a special case, it is always treated as allocated */ 77 Assert(!crHashIdPoolIsIdFree(pool, 0)); 78 79 /* first ensure entries have correct values */ 80 RTListForEach(&pool->freeList, i, FreeElem, Node) 81 { 82 Assert(i->min >= CR_HASH_ID_MIN); 83 Assert(i->max <= CR_HASH_ID_MAX); 84 Assert(i->min < i->max); 85 } 86 87 /* now ensure entries do not intersect */ 88 /* and that they are sorted */ 89 RTListForEach(&pool->freeList, i, FreeElem, Node) 90 { 91 Assert(min < i->min); 92 min = i->max; 93 } 94 } 95 96 static void crHashIdPoolDbgCheckUsed( const CRHashIdPool *pool, GLuint start, GLuint count, GLboolean fUsed ) 97 { 98 GLuint i; 99 CRASSERT(count); 100 CRASSERT(start >= CR_HASH_ID_MIN); 101 CRASSERT(start + count <= CR_HASH_ID_MAX); 102 CRASSERT(start + count > start); 103 for (i = 0; i < count; ++i) 104 { 105 Assert(!fUsed == !!crHashIdPoolIsIdFree( pool, start + i )); 106 } 107 } 108 109 # define CR_HASH_IDPOOL_DBG_CHECK_USED(_p, _start, _count, _used) do { \ 110 crHashIdPoolDbgCheckConsistency((_p)); \ 111 crHashIdPoolDbgCheckUsed( (_p), (_start), (_count), (_used) ); \ 112 } while (0) 113 114 # define CR_HASH_IDPOOL_DBG_CHECK_CONSISTENCY(_p) do { crHashIdPoolDbgCheckConsistency((_p)); } while (0) 115 #else 116 # define CR_HASH_IDPOOL_DBG_CHECK_USED(_p, _start, _count, _used) do { } while (0) 117 # define CR_HASH_IDPOOL_DBG_CHECK_CONSISTENCY(_p) do { } while (0) 118 #endif 64 119 65 120 /* … … 69 124 static GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count ) 70 125 { 71 FreeElem *f ;126 FreeElem *f, *next; 72 127 GLuint ret; 73 128 74 129 CRASSERT(count > 0); 75 76 f = pool->freeList; 77 while (f) 78 { 79 if (f->max - f->min + 1 >= (GLuint) count) 130 RTListForEachSafe(&pool->freeList, f, next, FreeElem, Node) 131 { 132 Assert(f->max > f->min); 133 if (f->max - f->min >= (GLuint) count) 80 134 { 81 135 /* found a sufficiently large enough block */ 82 136 ret = f->min; 83 137 f->min += count; 84 85 138 if (f->min == f->max) 86 139 { 87 /* remove this block from linked list */ 88 if (f == pool->freeList) 89 { 90 /* remove from head */ 91 pool->freeList = pool->freeList->next; 92 pool->freeList->prev = NULL; 93 } 94 else 95 { 96 /* remove from elsewhere */ 97 f->prev->next = f->next; 98 f->next->prev = f->prev; 99 } 140 RTListNodeRemove(&f->Node); 100 141 crFree(f); 101 142 } 102 143 103 #ifdef DEBUG 104 /* make sure the IDs really are allocated */ 105 { 106 GLuint i; 107 for (i = 0; i < count; i++) 108 { 109 //CRASSERT(crHashIdPoolIsIdUsed(pool, ret + i)); 110 } 111 } 112 #endif 113 144 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, ret, count, GL_TRUE); 114 145 return ret; 115 146 } 116 else {117 f = f->next;118 }119 147 } 120 148 121 149 /* failed to find free block */ 122 crDebug("crHashIdPoolAllocBlock failed"); 150 crWarning("crHashIdPoolAllocBlock failed"); 151 CR_HASH_IDPOOL_DBG_CHECK_CONSISTENCY(pool); 123 152 return 0; 124 153 } … … 130 159 static void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count ) 131 160 { 132 FreeElem *i; 133 FreeElem *newelem; 134 135 /*********************************/ 136 /* Add the name to the freeList */ 137 /* Find the bracketing sequences */ 138 139 for (i = pool->freeList; i && i->next && i->next->min < first; i = i->next) 140 { 141 /* EMPTY BODY */ 142 } 143 144 /* j will always be valid */ 145 if (!i) { 161 FreeElem *f; 162 GLuint last; 163 GLuint newMax; 164 FreeElem *cur, *curNext; 165 166 /* null is a special case, it is always treated as allocated */ 167 if (!first) 168 { 169 Assert(!crHashIdPoolIsIdFree(pool, 0)); 170 ++first; 171 --count; 172 if (!count) 173 return; 174 } 175 176 last = first + count; 177 CRASSERT(count > 0); 178 CRASSERT(last > first); 179 CRASSERT(first >= CR_HASH_ID_MIN); 180 CRASSERT(last <= CR_HASH_ID_MAX); 181 182 /* the id list is sorted, first find a place to insert */ 183 RTListForEach(&pool->freeList, f, FreeElem, Node) 184 { 185 Assert(f->max > f->min); 186 187 if (f->max < first) 188 continue; 189 190 if (f->min > last) 191 { 192 /* we are here because first is > than prevEntry->max 193 * otherwise the previous loop iterations should handle that */ 194 FreeElem *elem = (FreeElem *) crCalloc(sizeof(FreeElem)); 195 elem->min = first; 196 elem->max = last; 197 RTListNodeInsertBefore(&f->Node, &elem->Node); 198 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE); 199 return; 200 } 201 202 /* now we have f->min <= last and f->max >= first, 203 * so we have either intersection */ 204 205 if (f->min > first) 206 f->min = first; /* first is guarantied not to touch any prev regions */ 207 208 newMax = last; 209 210 if (f->max >= last) 211 { 212 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE); 213 return; 214 } 215 216 for (cur = RTListNodeGetNext(&f->Node, FreeElem, Node), 217 curNext = RT_FROM_MEMBER(cur->Node.pNext, FreeElem, Node); 218 !RTListNodeIsDummy(&pool->freeList, cur, FreeElem, Node); 219 cur = curNext, 220 curNext = RT_FROM_MEMBER((cur)->Node.pNext, FreeElem, Node) ) 221 { 222 if (cur->min > last) 223 break; 224 225 newMax = cur->max; 226 RTListNodeRemove(&cur->Node); 227 crFree(cur); 228 229 if (newMax >= last) 230 break; 231 } 232 233 f->max = newMax; 234 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE); 146 235 return; 147 236 } 148 if (!i->next && i->max == first) { 149 return; 150 } 151 152 /* Case: j:(~,first-1) */ 153 if (i->max + 1 == first) 154 { 155 i->max += count; 156 if (i->next && i->max+1 >= i->next->min) 157 { 158 /* Collapse */ 159 i->next->min = i->min; 160 i->next->prev = i->prev; 161 if (i->prev) 162 { 163 i->prev->next = i->next; 164 } 165 if (i == pool->freeList) 166 { 167 pool->freeList = i->next; 168 } 169 crFree(i); 170 } 171 return; 172 } 173 174 /* Case: j->next: (first+1, ~) */ 175 if (i->next && i->next->min - count == first) 176 { 177 i->next->min -= count; 178 if (i->max + 1 >= i->next->min) 179 { 180 /* Collapse */ 181 i->next->min = i->min; 182 i->next->prev = i->prev; 183 if (i->prev) 184 { 185 i->prev->next = i->next; 186 } 187 if (i == pool->freeList) 188 { 189 pool->freeList = i->next; 190 } 191 crFree(i); 192 } 193 return; 194 } 195 196 /* Case: j: (first+1, ~) j->next: null */ 197 if (!i->next && i->min - count == first) 198 { 199 i->min -= count; 200 return; 201 } 202 203 /* allocate a new FreeElem node */ 204 newelem = (FreeElem *) crCalloc(sizeof(FreeElem)); 205 newelem->min = first; 206 newelem->max = first + count - 1; 207 208 /* Case: j: (~,first-(2+)) j->next: (first+(2+), ~) or null */ 209 if (first > i->max) 210 { 211 newelem->prev = i; 212 newelem->next = i->next; 213 if (i->next) 214 { 215 i->next->prev = newelem; 216 } 217 i->next = newelem; 218 return; 219 } 220 221 /* Case: j: (first+(2+), ~) */ 222 /* Can only happen if j = t->freeList! */ 223 if (i == pool->freeList && i->min > first) 224 { 225 newelem->next = i; 226 newelem->prev = i->prev; 227 i->prev = newelem; 228 pool->freeList = newelem; 229 return; 230 } 237 238 /* we are here because either the list is empty or because all list rande elements have smaller values */ 239 f = (FreeElem *) crCalloc(sizeof(FreeElem)); 240 f->min = first; 241 f->max = last; 242 RTListAppend(&pool->freeList, &f->Node); 243 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, first, count, GL_FALSE); 231 244 } 232 245 … … 238 251 static GLboolean crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id ) 239 252 { 240 FreeElem *f; 241 242 f = pool->freeList; 243 while (f) 244 { 245 if (id >= f->min && id <= f->max) 246 { 247 /* found the block */ 248 if (id == f->min) 253 FreeElem *f, *next; 254 255 if (!id) 256 { 257 /* null is a special case, it is always treated as allocated */ 258 Assert(!crHashIdPoolIsIdFree(pool, 0)); 259 return GL_FALSE; 260 } 261 262 // Assert(id != 2); 263 264 RTListForEachSafe(&pool->freeList, f, next, FreeElem, Node) 265 { 266 if (f->max <= id) 267 continue; 268 if (f->min > id) 269 { 270 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE); 271 return GL_FALSE; 272 } 273 274 /* f->min <= id && f->max > id */ 275 if (id > f->min) 276 { 277 if (id + 1 < f->max) 249 278 { 250 f->min++; 279 FreeElem *elem = (FreeElem *) crCalloc(sizeof(FreeElem)); 280 elem->min = id + 1; 281 elem->max = f->max; 282 RTListNodeInsertAfter(&f->Node, &elem->Node); 251 283 } 252 else if (id == f->max) 284 f->max = id; 285 286 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE); 287 } 288 else 289 { 290 Assert(id == f->min); 291 if (id + 1 < f->max) 253 292 { 254 f->max--; 293 f->min = id + 1; 294 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE); 255 295 } 256 296 else 257 297 { 258 /* somewhere in the middle - split the block */ 259 FreeElem *newelem = (FreeElem *) crCalloc(sizeof(FreeElem)); 260 newelem->min = id + 1; 261 newelem->max = f->max; 262 f->max = id - 1; 263 newelem->next = f->next; 264 if (f->next) 265 f->next->prev = newelem; 266 newelem->prev = f; 267 f->next = newelem; 298 RTListNodeRemove(&f->Node); 299 crFree(f); 300 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE); 268 301 } 269 return GL_TRUE; 270 } 271 f = f->next; 302 } 303 304 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE); 305 return GL_TRUE; 272 306 } 273 307 274 308 /* if we get here, the ID was already allocated - that's OK */ 309 CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE); 275 310 return GL_FALSE; 276 311 } … … 282 317 static GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id ) 283 318 { 284 FreeElem *i; 285 286 /* First find which region it fits in */ 287 for (i = pool->freeList; i && !(i->min <= id && id <= i->max); i=i->next) 288 { 289 /* EMPTY BODY */ 290 } 291 292 if (i) 319 FreeElem *f; 320 CRASSERT(id >= 0); 321 CRASSERT(id <= CR_HASH_ID_MAX); 322 323 RTListForEach(&pool->freeList, f, FreeElem, Node) 324 { 325 if (f->max <= id) 326 continue; 327 if (f->min > id) 328 return GL_FALSE; 293 329 return GL_TRUE; 294 else295 330 } 331 return GL_FALSE; 296 332 } 297 333
Note:
See TracChangeset
for help on using the changeset viewer.