Path: blob/21.2-virgl/src/gallium/auxiliary/util/u_handle_table.c
4561 views
/**************************************************************************1*2* Copyright 2008 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/**28* @file29* Generic handle table implementation.30*31* @author José Fonseca <[email protected]>32*/333435#include "pipe/p_compiler.h"36#include "util/u_debug.h"3738#include "util/u_memory.h"39#include "util/u_handle_table.h"404142#define HANDLE_TABLE_INITIAL_SIZE 16434445struct handle_table46{47/** Object array. Empty handles have a null object */48void **objects;4950/** Number of objects the handle can currently hold */51unsigned size;52/** Number of consecutive objects allocated at the start of the table */53unsigned filled;5455/** Optional object destructor */56void (*destroy)(void *object);57};585960struct handle_table *61handle_table_create(void)62{63struct handle_table *ht;6465ht = MALLOC_STRUCT(handle_table);66if (!ht)67return NULL;6869ht->objects = (void **)CALLOC(HANDLE_TABLE_INITIAL_SIZE, sizeof(void *));70if(!ht->objects) {71FREE(ht);72return NULL;73}7475ht->size = HANDLE_TABLE_INITIAL_SIZE;76ht->filled = 0;7778ht->destroy = NULL;7980return ht;81}828384void85handle_table_set_destroy(struct handle_table *ht,86void (*destroy)(void *object))87{88assert(ht);89if (!ht)90return;91ht->destroy = destroy;92}939495/**96* Resize the table if necessary97*/98static inline int99handle_table_resize(struct handle_table *ht,100unsigned minimum_size)101{102unsigned new_size;103void **new_objects;104105if(ht->size > minimum_size)106return ht->size;107108new_size = ht->size;109while(!(new_size > minimum_size))110new_size *= 2;111assert(new_size);112113new_objects = (void **)REALLOC((void *)ht->objects,114ht->size*sizeof(void *),115new_size*sizeof(void *));116if (!new_objects)117return 0;118119memset(new_objects + ht->size, 0, (new_size - ht->size)*sizeof(void *));120121ht->size = new_size;122ht->objects = new_objects;123124return ht->size;125}126127128static inline void129handle_table_clear(struct handle_table *ht,130unsigned index)131{132void *object;133134/* The order here is important so that the object being destroyed is not135* present in the table when seen by the destroy callback, because the136* destroy callback may directly or indirectly call the other functions in137* this module.138*/139140object = ht->objects[index];141if (object) {142ht->objects[index] = NULL;143144if(ht->destroy)145ht->destroy(object);146}147}148149150unsigned151handle_table_add(struct handle_table *ht,152void *object)153{154unsigned index;155unsigned handle;156157assert(ht);158assert(object);159if(!object || !ht)160return 0;161162/* linear search for an empty handle */163while(ht->filled < ht->size) {164if(!ht->objects[ht->filled])165break;166++ht->filled;167}168169index = ht->filled;170handle = index + 1;171172/* check integer overflow */173if(!handle)174return 0;175176/* grow the table if necessary */177if(!handle_table_resize(ht, index))178return 0;179180assert(!ht->objects[index]);181ht->objects[index] = object;182++ht->filled;183184return handle;185}186187188unsigned189handle_table_set(struct handle_table *ht,190unsigned handle,191void *object)192{193unsigned index;194195assert(ht);196assert(handle);197if(!handle || !ht)198return 0;199200assert(object);201if (!object)202return 0;203204index = handle - 1;205206/* grow the table if necessary */207if(!handle_table_resize(ht, index))208return 0;209210handle_table_clear(ht, index);211212ht->objects[index] = object;213214return handle;215}216217218void *219handle_table_get(struct handle_table *ht,220unsigned handle)221{222void *object;223224assert(ht);225assert(handle);226if(!handle || !ht || handle > ht->size)227return NULL;228229object = ht->objects[handle - 1];230231return object;232}233234235void236handle_table_remove(struct handle_table *ht,237unsigned handle)238{239void *object;240unsigned index;241242assert(ht);243assert(handle);244if(!handle || !ht || handle > ht->size)245return;246247index = handle - 1;248object = ht->objects[index];249if (!object)250return;251252handle_table_clear(ht, index);253254if(index < ht->filled)255ht->filled = index;256}257258259unsigned260handle_table_get_next_handle(struct handle_table *ht,261unsigned handle)262{263unsigned index;264265for(index = handle; index < ht->size; ++index) {266if(ht->objects[index])267return index + 1;268}269270return 0;271}272273274unsigned275handle_table_get_first_handle(struct handle_table *ht)276{277return handle_table_get_next_handle(ht, 0);278}279280281void282handle_table_destroy(struct handle_table *ht)283{284unsigned index;285assert(ht);286287if (!ht)288return;289290if(ht->destroy)291for(index = 0; index < ht->size; ++index)292handle_table_clear(ht, index);293294FREE(ht->objects);295FREE(ht);296}297298299300