VirtualBox

Changeset 44193 in vbox for trunk/src/VBox/GuestHost


Ignore:
Timestamp:
Dec 20, 2012 11:34:25 PM (12 years ago)
Author:
vboxsync
Message:

crOpenGL: hash table index pool rewrite

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/OpenGL/util/hash.c

    r44125 r44193  
    1010#include "cr_error.h"
    1111
     12#include <iprt/list.h>
     13
    1214#define CR_MAXUINT             ((GLuint) 0xFFFFFFFF)
     15#define CR_HASH_ID_MIN ((GLuint)1)
     16#define CR_HASH_ID_MAX CR_MAXUINT
    1317
    1418#define CR_NUM_BUCKETS 1047
    1519
    1620typedef struct FreeElemRec {
     21    RTLISTNODE Node;
    1722    GLuint min;
    1823    GLuint max;
    19     struct FreeElemRec *next;
    20     struct FreeElemRec *prev;
    2124} FreeElem;
    2225
    2326typedef struct CRHashIdPoolRec {
    24     FreeElem *freeList;
     27    RTLISTNODE freeList;
    2528} CRHashIdPool;
    2629
     
    4447{
    4548    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);
    5154    return pool;
    5255}
     
    5558{
    5659    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    {
    6062        crFree(i);
    6163    }
     64
    6265    crFree(pool);
    6366}
     67
     68static GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id );
     69
     70#ifdef DEBUG_misha
     71static 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
     96static 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
    64119
    65120/*
     
    69124static GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count )
    70125{
    71     FreeElem *f;
     126    FreeElem *f, *next;
    72127    GLuint ret;
    73128
    74129    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)
    80134        {
    81135            /* found a sufficiently large enough block */
    82136            ret = f->min;
    83137            f->min += count;
    84 
    85138            if (f->min == f->max)
    86139            {
    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);
    100141                crFree(f);
    101142            }
    102143
    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);
    114145            return ret;
    115146        }
    116         else {
    117             f = f->next;
    118         }
    119147    }
    120148
    121149    /* failed to find free block */
    122     crDebug("crHashIdPoolAllocBlock failed");
     150    crWarning("crHashIdPoolAllocBlock failed");
     151    CR_HASH_IDPOOL_DBG_CHECK_CONSISTENCY(pool);
    123152    return 0;
    124153}
     
    130159static void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count )
    131160{
    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);
    146235        return;
    147236    }
    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);
    231244}
    232245
     
    238251static GLboolean crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id )
    239252{
    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)
    249278            {
    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);
    251283            }
    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)
    253292            {
    254                 f->max--;
     293                f->min = id + 1;
     294                CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
    255295            }
    256296            else
    257297            {
    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);
    268301            }
    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;
    272306    }
    273307
    274308    /* if we get here, the ID was already allocated - that's OK */
     309    CR_HASH_IDPOOL_DBG_CHECK_USED(pool, id, 1, GL_TRUE);
    275310    return GL_FALSE;
    276311}
     
    282317static GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id )
    283318{
    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;
    293329        return GL_TRUE;
    294     else
    295         return GL_FALSE;
     330    }
     331    return GL_FALSE;
    296332}
    297333
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette