struct pool_arena
{
- struct pool_arena* next;
- char* current;
+ struct list entry;
+ char *current;
+ char *end;
};
-void pool_init(struct pool* a, unsigned arena_size)
+void pool_init(struct pool* a, size_t arena_size)
{
+ list_init( &a->arena_list );
+ list_init( &a->arena_full );
a->arena_size = arena_size;
- a->first = NULL;
}
void pool_destroy(struct pool* pool)
struct pool_arena* next;
#ifdef USE_STATS
- unsigned alloc, used, num;
-
- for (alloc = used = num = 0, arena = pool->first; arena; arena = arena->next)
+ size_t alloc, used, num;
+
+ alloc = used = num = 0;
+ LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry )
{
- alloc += pool->arena_size;
+ alloc += arena->end - (char *)arena;
used += arena->current - (char*)arena;
num++;
}
- FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n"
- "\t\t\t\tnon-allocation ratio: %.2f%%\n",
- pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0);
+ LIST_FOR_EACH_ENTRY( arena, &pool->arena_full, struct pool_arena, entry )
+ {
+ alloc += arena->end - (char *)arena;
+ used += arena->current - (char*)arena;
+ num++;
+ }
+ if (alloc == 0) alloc = 1; /* avoid division by zero */
+ FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas, non-allocation ratio: %.2f%%\n",
+ pool, (unsigned)(alloc >> 10), (unsigned)(used >> 10), (unsigned)num,
+ 100.0 - (float)used / (float)alloc * 100.0);
#endif
- for (arena = pool->first; arena; arena = next)
+ LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_list, struct pool_arena, entry )
{
- next = arena->next;
+ list_remove( &arena->entry );
+ HeapFree(GetProcessHeap(), 0, arena);
+ }
+ LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_full, struct pool_arena, entry )
+ {
+ list_remove( &arena->entry );
HeapFree(GetProcessHeap(), 0, arena);
}
- pool_init(pool, 0);
}
-void* pool_alloc(struct pool* pool, unsigned len)
+void* pool_alloc(struct pool* pool, size_t len)
{
struct pool_arena* arena;
void* ret;
+ size_t size;
len = (len + 3) & ~3; /* round up size on DWORD boundary */
- assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
- for (arena = pool->first; arena; arena = arena->next)
+ LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry )
{
- if ((char*)arena + pool->arena_size - arena->current >= len)
+ if (arena->end - arena->current >= len)
{
ret = arena->current;
arena->current += len;
+ if (arena->current + 16 >= arena->end)
+ {
+ list_remove( &arena->entry );
+ list_add_tail( &pool->arena_full, &arena->entry );
+ }
return ret;
}
}
- arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size);
- if (!arena) {FIXME("OOM\n");return NULL;}
+ size = max( pool->arena_size, len );
+ arena = HeapAlloc(GetProcessHeap(), 0, size + sizeof(struct pool_arena));
+ if (!arena) return NULL;
- ret = (char*)arena + sizeof(*arena);
- arena->next = pool->first;
- pool->first = arena;
+ ret = arena + 1;
arena->current = (char*)ret + len;
+ arena->end = (char*)ret + size;
+ if (arena->current + 16 >= arena->end)
+ list_add_tail( &pool->arena_full, &arena->entry );
+ else
+ list_add_head( &pool->arena_list, &arena->entry );
return ret;
}
return sa->elements.num_elts;
}
-unsigned hash_table_hash(const char* name, unsigned num_buckets)
+static unsigned hash_table_hash(const char* name, unsigned num_buckets)
{
unsigned hash = 0;
while (*name)
void hash_table_init(struct pool* pool, struct hash_table* ht, unsigned num_buckets)
{
ht->num_elts = 0;
- ht->buckets = pool_alloc(pool, num_buckets * sizeof(struct hash_table_elt*));
- assert(ht->buckets);
ht->num_buckets = num_buckets;
- memset(ht->buckets, 0, num_buckets * sizeof(struct hash_table_elt*));
+ ht->pool = pool;
+ ht->buckets = NULL;
}
void hash_table_destroy(struct hash_table* ht)
void hash_table_add(struct hash_table* ht, struct hash_table_elt* elt)
{
unsigned hash = hash_table_hash(elt->name, ht->num_buckets);
- struct hash_table_elt** p;
+
+ if (!ht->buckets)
+ {
+ ht->buckets = pool_alloc(ht->pool, ht->num_buckets * sizeof(struct hash_table_bucket));
+ assert(ht->buckets);
+ memset(ht->buckets, 0, ht->num_buckets * sizeof(struct hash_table_bucket));
+ }
/* in some cases, we need to get back the symbols of same name in the order
* in which they've been inserted. So insert new elements at the end of the list.
*/
- for (p = &ht->buckets[hash]; *p; p = &((*p)->next));
- *p = elt;
+ if (!ht->buckets[hash].first)
+ {
+ ht->buckets[hash].first = elt;
+ }
+ else
+ {
+ ht->buckets[hash].last->next = elt;
+ }
+ ht->buckets[hash].last = elt;
elt->next = NULL;
ht->num_elts++;
}
-void* hash_table_find(const struct hash_table* ht, const char* name)
-{
- unsigned hash = hash_table_hash(name, ht->num_buckets);
- struct hash_table_elt* elt;
-
- for (elt = ht->buckets[hash]; elt; elt = elt->next)
- if (!strcmp(name, elt->name)) return elt;
- return NULL;
-}
-
void hash_table_iter_init(const struct hash_table* ht,
struct hash_table_iter* hti, const char* name)
{
void* hash_table_iter_up(struct hash_table_iter* hti)
{
+ if (!hti->ht->buckets) return NULL;
+
if (hti->element) hti->element = hti->element->next;
while (!hti->element && hti->index < hti->last)
- hti->element = hti->ht->buckets[++hti->index];
+ hti->element = hti->ht->buckets[++hti->index].first;
return hti->element;
}