Reduce number of malloc/free by automatically created one stringshare

per tree node.


SVN revision: 36165
This commit is contained in:
Cedric BAIL 2008-09-22 13:06:29 +00:00
parent 3fc07d2aac
commit d3e0b59223
1 changed files with 44 additions and 26 deletions

View File

@ -106,6 +106,8 @@ struct _Eina_Stringshare_Node
int length; int length;
int references; int references;
Eina_Bool begin : 1;
}; };
static Eina_Stringshare *share = NULL; static Eina_Stringshare *share = NULL;
@ -231,7 +233,7 @@ eina_stringshare_shutdown()
Eina_Stringshare_Node *el = save->head; Eina_Stringshare_Node *el = save->head;
save->head = el->next; save->head = el->next;
free(el); if (el->begin == EINA_FALSE) free(el);
} }
free(save); free(save);
} }
@ -262,6 +264,8 @@ eina_stringshare_shutdown()
EAPI const char * EAPI const char *
eina_stringshare_add(const char *str) eina_stringshare_add(const char *str)
{ {
Eina_Stringshare_Node *nel = NULL;
Eina_Stringshare_Node *tmp;
Eina_Stringshare_Head *ed; Eina_Stringshare_Head *ed;
Eina_Stringshare_Node *el; Eina_Stringshare_Node *el;
char *el_str; char *el_str;
@ -277,7 +281,7 @@ eina_stringshare_add(const char *str)
EINA_RBTREE_CMP_KEY_CB(_eina_stringshare_cmp), NULL); EINA_RBTREE_CMP_KEY_CB(_eina_stringshare_cmp), NULL);
if (!ed) if (!ed)
{ {
ed = malloc(sizeof (Eina_Stringshare_Head)); ed = malloc(sizeof (Eina_Stringshare_Head) + sizeof (Eina_Stringshare_Node) + slen);
if (!ed) return NULL; if (!ed) return NULL;
ed->hash = hash; ed->hash = hash;
ed->head = NULL; ed->head = NULL;
@ -285,29 +289,44 @@ eina_stringshare_add(const char *str)
share->buckets[hash_num] = (Eina_Stringshare_Head*) eina_rbtree_inline_insert((Eina_Rbtree*) share->buckets[hash_num], share->buckets[hash_num] = (Eina_Stringshare_Head*) eina_rbtree_inline_insert((Eina_Rbtree*) share->buckets[hash_num],
&ed->node, &ed->node,
EINA_RBTREE_CMP_NODE_CB(_eina_stringshare_node), NULL); EINA_RBTREE_CMP_NODE_CB(_eina_stringshare_node), NULL);
nel = (Eina_Stringshare_Node*) (ed + 1);
nel->begin = EINA_TRUE;
} }
for (el = ed->head; for (el = ed->head, tmp = NULL;
el && slen != el->length && memcmp(str, (const char*) (el + 1), slen) != 0; el && slen != el->length && memcmp(str, (const char*) (el + 1), slen) != 0;
el = el->next) tmp = el, el = el->next)
; ;
if (el) if (el)
{ {
if (tmp)
{
tmp->next = el->next;
el->next = ed->head;
ed->head = el;
}
el->references++; el->references++;
return (const char*) (el + 1); return (const char*) (el + 1);
} }
el = malloc(sizeof (Eina_Stringshare_Node) + slen); if (!nel)
if (!el) return NULL; {
el->references = 1; nel = malloc(sizeof (Eina_Stringshare_Node) + slen);
el->length = slen; if (!nel) return NULL;
nel->begin = EINA_FALSE;
}
el_str = (char*) (el + 1); nel->references = 1;
nel->length = slen;
el_str = (char*) (nel + 1);
memcpy(el_str, str, slen); memcpy(el_str, str, slen);
el->next = ed->head; nel->next = ed->head;
ed->head = el; ed->head = nel;
return el_str; return el_str;
} }
@ -345,26 +364,25 @@ eina_stringshare_del(const char *str)
el = el->next) el = el->next)
; ;
if (el) if (!el) goto on_error;
{
el->references--;
if (el->references == 0)
{
if (prev) prev->next = el->next;
else ed->head = el->next;
free(el);
if (ed->head == NULL) el->references--;
{ if (el->references == 0)
share->buckets[hash_num] = (Eina_Stringshare_Head*) eina_rbtree_inline_remove(&share->buckets[hash_num]->node, {
if (prev) prev->next = el->next;
else ed->head = el->next;
if (el->begin == EINA_FALSE) free(el);
if (ed->head == NULL)
{
share->buckets[hash_num] = (Eina_Stringshare_Head*) eina_rbtree_inline_remove(&share->buckets[hash_num]->node,
&ed->node, &ed->node,
EINA_RBTREE_CMP_NODE_CB(_eina_stringshare_node), EINA_RBTREE_CMP_NODE_CB(_eina_stringshare_node),
NULL); NULL);
free(ed); free(ed);
}
} }
return ;
} }
return ;
on_error: on_error:
EINA_ERROR_PWARN("EEEK trying to del non-shared stringshare \"%s\"\n", str); EINA_ERROR_PWARN("EEEK trying to del non-shared stringshare \"%s\"\n", str);