u_handle_table.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00036 #include "pipe/p_compiler.h"
00037 #include "pipe/p_debug.h"
00038 
00039 #include "util/u_memory.h"
00040 #include "util/u_handle_table.h"
00041 
00042 
00043 #define HANDLE_TABLE_INITIAL_SIZE 16  
00044 
00045 
00046 struct handle_table
00047 {
00049    void **objects;
00050    
00052    unsigned size;
00054    unsigned filled;
00055    
00057    void (*destroy)(void *object);
00058 };
00059 
00060 
00061 struct handle_table *
00062 handle_table_create(void)
00063 {
00064    struct handle_table *ht;
00065    
00066    ht = MALLOC_STRUCT(handle_table);
00067    if(!ht)
00068       return NULL;
00069    
00070    ht->objects = (void **)CALLOC(HANDLE_TABLE_INITIAL_SIZE, sizeof(void *));
00071    if(!ht->objects) {
00072       FREE(ht);
00073       return NULL;
00074    }
00075    
00076    ht->size = HANDLE_TABLE_INITIAL_SIZE;
00077    ht->filled = 0;
00078    
00079    ht->destroy = NULL;
00080    
00081    return ht;
00082 }
00083 
00084 
00085 void
00086 handle_table_set_destroy(struct handle_table *ht,
00087                          void (*destroy)(void *object))
00088 {
00089    assert(ht);
00090    ht->destroy = destroy;
00091 }
00092 
00093 
00097 static INLINE int
00098 handle_table_resize(struct handle_table *ht,
00099                     unsigned minimum_size)
00100 {
00101    unsigned new_size;
00102    void **new_objects;
00103 
00104    if(ht->size > minimum_size)
00105       return ht->size;
00106 
00107    new_size = ht->size;
00108    while(!(new_size > minimum_size))
00109       new_size *= 2;
00110    assert(new_size);
00111    
00112    new_objects = (void **)REALLOC((void *)ht->objects,
00113                                   ht->size*sizeof(void *),
00114                                   new_size*sizeof(void *));
00115    if(!new_objects)
00116       return 0;
00117    
00118    memset(new_objects + ht->size, 0, (new_size - ht->size)*sizeof(void *));
00119    
00120    ht->size = new_size;
00121    ht->objects = new_objects;
00122    
00123    return ht->size;
00124 }
00125 
00126 
00127 static INLINE void
00128 handle_table_clear(struct handle_table *ht, 
00129                    unsigned index)
00130 {
00131    void *object;
00132    
00133    /* The order here is important so that the object being destroyed is not
00134     * present in the table when seen by the destroy callback, because the 
00135     * destroy callback may directly or indirectly call the other functions in 
00136     * this module.
00137     */
00138 
00139    object = ht->objects[index];
00140    if(object) {
00141       ht->objects[index] = NULL;
00142       
00143       if(ht->destroy)
00144          ht->destroy(object);
00145    }   
00146 }
00147 
00148 
00149 unsigned
00150 handle_table_add(struct handle_table *ht, 
00151                  void *object)
00152 {
00153    unsigned index;
00154    unsigned handle;
00155    
00156    assert(ht);
00157    assert(object);
00158    if(!object)
00159       return 0;
00160 
00161    /* linear search for an empty handle */
00162    while(ht->filled < ht->size) {
00163       if(!ht->objects[ht->filled])
00164          break;
00165       ++ht->filled;
00166    }
00167   
00168    index = ht->filled;
00169    handle = index + 1;
00170    
00171    /* check integer overflow */
00172    if(!handle)
00173       return 0;
00174    
00175    /* grow the table if necessary */
00176    if(!handle_table_resize(ht, index))
00177       return 0;
00178 
00179    assert(!ht->objects[index]);
00180    ht->objects[index] = object;
00181    ++ht->filled;
00182    
00183    return handle;
00184 }
00185 
00186 
00187 unsigned
00188 handle_table_set(struct handle_table *ht, 
00189                  unsigned handle,
00190                  void *object)
00191 {
00192    unsigned index;
00193    
00194    assert(ht);
00195    assert(handle);
00196    if(!handle)
00197       return 0;
00198 
00199    assert(object);
00200    if(!object)
00201       return 0;
00202    
00203    index = handle - 1;
00204 
00205    /* grow the table if necessary */
00206    if(!handle_table_resize(ht, index))
00207       return 0;
00208 
00209    handle_table_clear(ht, index);
00210 
00211    ht->objects[index] = object;
00212    
00213    return handle;
00214 }
00215 
00216 
00217 void *
00218 handle_table_get(struct handle_table *ht, 
00219                  unsigned handle)
00220 {
00221    void *object;
00222    
00223    assert(ht);
00224    assert(handle);
00225    if(!handle || handle > ht->size)
00226       return NULL;
00227 
00228    object = ht->objects[handle - 1];
00229    
00230    return object;
00231 }
00232 
00233 
00234 void
00235 handle_table_remove(struct handle_table *ht, 
00236                     unsigned handle)
00237 {
00238    void *object;
00239    unsigned index;
00240    
00241    assert(ht);
00242    assert(handle);
00243    if(!handle || handle > ht->size)
00244       return;
00245 
00246    index = handle - 1;
00247    object = ht->objects[index];
00248    if(!object)
00249       return;
00250    
00251    handle_table_clear(ht, index);
00252 
00253    if(index < ht->filled)
00254       ht->filled = index;
00255 }
00256 
00257 
00258 unsigned
00259 handle_table_get_next_handle(struct handle_table *ht, 
00260                              unsigned handle)
00261 {
00262    unsigned index;
00263    
00264    for(index = handle; index < ht->size; ++index) {
00265       if(ht->objects[index])
00266          return index + 1;
00267    }
00268 
00269    return 0;
00270 }
00271 
00272 
00273 unsigned
00274 handle_table_get_first_handle(struct handle_table *ht)
00275 {
00276    return handle_table_get_next_handle(ht, 0);
00277 }
00278 
00279 
00280 void
00281 handle_table_destroy(struct handle_table *ht)
00282 {
00283    unsigned index;
00284    assert(ht);
00285 
00286    if(ht->destroy)
00287       for(index = 0; index < ht->size; ++index)
00288          handle_table_clear(ht, index);
00289    
00290    FREE(ht->objects);
00291    FREE(ht);
00292 }
00293 

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4