tag: optimize tag_dup(), copy item references

Don't call tag_pool_get_item() for duplicating tags, just increase the
item's reference counter instead.
This commit is contained in:
Max Kellermann 2008-08-29 15:04:49 +02:00
parent d8ad109e10
commit d38d2bc353
3 changed files with 42 additions and 7 deletions

View File

@ -313,9 +313,11 @@ struct tag *tag_dup(const struct tag *tag)
ret = tag_new();
ret->time = tag->time;
ret->numOfItems = tag->numOfItems;
ret->items = xmalloc(ret->numOfItems * sizeof(ret->items[0]));
for (i = 0; i < tag->numOfItems; i++) {
tag_add_item(ret, tag->items[i]->type, tag->items[i]->value);
ret->items[i] = tag_pool_dup_item(tag->items[i]);
}
return ret;

View File

@ -61,6 +61,19 @@ tag_item_to_slot(struct tag_item *item)
return (struct slot*)(((char*)item) - offsetof(struct slot, item));
}
static struct slot *slot_alloc(struct slot *next,
enum tag_type type,
const char *value, int length)
{
struct slot *slot = xmalloc(sizeof(*slot) + length);
slot->next = next;
slot->ref = 1;
slot->item.type = type;
memcpy(slot->item.value, value, length);
slot->item.value[length] = 0;
return slot;
}
struct tag_item *tag_pool_get_item(enum tag_type type,
const char *value, int length)
{
@ -76,16 +89,34 @@ struct tag_item *tag_pool_get_item(enum tag_type type,
}
}
slot = xmalloc(sizeof(*slot) + length);
slot->next = *slot_p;
slot->ref = 1;
slot->item.type = type;
memcpy(slot->item.value, value, length);
slot->item.value[length] = 0;
slot = slot_alloc(*slot_p, type, value, length);
*slot_p = slot;
return &slot->item;
}
struct tag_item *tag_pool_dup_item(struct tag_item *item)
{
struct slot *slot = tag_item_to_slot(item);
assert(slot->ref > 0);
if (slot->ref < 0xff) {
++slot->ref;
return item;
} else {
/* the reference counter overflows above 0xff;
duplicate the item, and start with 1 */
size_t length = strlen(item->value);
struct slot **slot_p =
&slots[calc_hash_n(item->type, item->value,
length) % NUM_SLOTS];
slot = slot_alloc(*slot_p, item->type,
item->value, strlen(item->value));
*slot_p = slot;
return &slot->item;
}
}
void tag_pool_put_item(struct tag_item *item)
{
struct slot **slot_p, *slot;

View File

@ -26,6 +26,8 @@ struct tag_item;
struct tag_item *tag_pool_get_item(enum tag_type type,
const char *value, int length);
struct tag_item *tag_pool_dup_item(struct tag_item *item);
void tag_pool_put_item(struct tag_item *item);
#endif