00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00134
00135
00136
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
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
00172 if(!handle)
00173 return 0;
00174
00175
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
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