X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fhook.c;h=c3f3d911a0c055251ff03be53301e0e987670c11;hb=58c88a41c3beff0c4c6ff7d856ab2355820d9f16;hp=f92b397d3bbb1c370a97721a7574ca2414180dbb;hpb=47e763400230ba5cd55c377db531a4610f3c00ea;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/hook.c b/ltt/branches/poly/lttv/lttv/hook.c index f92b397d..c3f3d911 100644 --- a/ltt/branches/poly/lttv/lttv/hook.c +++ b/ltt/branches/poly/lttv/lttv/hook.c @@ -24,6 +24,7 @@ typedef struct _LttvHookClosure { LttvHook hook; void *hook_data; LttvHookPrio prio; + guint ref_count; } LttvHookClosure; gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b) @@ -49,27 +50,91 @@ void lttv_hooks_destroy(LttvHooks *h) void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p) { - LttvHookClosure c; - + LttvHookClosure *c, new_c; + guint i; + if(h == NULL)g_error("Null hook added"); - c.hook = f; - c.hook_data = hook_data; - c.prio = p; - g_array_append_val(h,c); - g_array_sort(h, (GCompareFunc)lttv_hooks_prio_compare); -} + new_c.hook = f; + new_c.hook_data = hook_data; + new_c.prio = p; + new_c.ref_count = 1; + + /* Preliminary check for duplication */ + /* only hook and hook data is checked */ + for(i = 0; i < h->len; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(new_c.hook == c->hook && new_c.hook_data == c->hook_data) { + g_assert(new_c.prio == c->prio); + c->ref_count++; + return; + } + } + + for(i = 0; i < h->len; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(new_c.prio < c->prio) { + g_array_insert_val(h,i,new_c); + return; + } + } + if(i == h->len) + g_array_append_val(h,new_c); +} -void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list) +/* lttv_hooks_add_list + * + * Adds a sorted list into another sorted list. + * + * Note : h->len is modified, but only incremented. This assures + * its coherence through the function. + * + * j is an index to the element following the last one added in the + * destination array. + */ +void lttv_hooks_add_list(LttvHooks *h, const LttvHooks *list) { - guint i; + guint i,j,k; + LttvHookClosure *c; + const LttvHookClosure *new_c; if(list == NULL) return; - for(i = 0 ; i < list->len; i++) { - g_array_append_val(h,g_array_index(list, LttvHookClosure, i)); + for(i = 0, j = 0 ; i < list->len; i++) { + new_c = &g_array_index(list, LttvHookClosure, i); + gboolean found=FALSE; + + /* Preliminary check for duplication */ + /* only hook and hook data is checked, not priority */ + for(k = 0; k < h->len; k++) { + c = &g_array_index(h, LttvHookClosure, k); + if(new_c->hook == c->hook && new_c->hook_data == c->hook_data) { + /* Found another identical entry : increment its ref_count and + * jump over the source index */ + g_assert(new_c->prio == c->prio); + found=TRUE; + c->ref_count++; + break; + } + } + + if(!found) { + /* If not found, add it to the destination array */ + while(j < h->len) { + c = &g_array_index(h, LttvHookClosure, j); + if(new_c->prio < c->prio) { + g_array_insert_val(h,j,*new_c); + j++; + break; + } + else j++; + } + if(j == h->len) { + g_array_append_val(h,*new_c); + j++; + } + } } - g_array_sort(h, (GCompareFunc)lttv_hooks_prio_compare); } @@ -84,9 +149,16 @@ void *lttv_hooks_remove(LttvHooks *h, LttvHook f) for(i = 0 ; i < h->len ; i++) { c = &g_array_index(h, LttvHookClosure, i); if(c->hook == f) { - hook_data = c->hook_data; - lttv_hooks_remove_by_position(h, i); - return hook_data; + if(c->ref_count == 1) { + hook_data = c->hook_data; + lttv_hooks_remove_by_position(h, i); + return hook_data; + } else { + g_assert(c->ref_count != 0); + c->ref_count--; + return NULL; /* We do not want anyone to free a hook_data + still referenced */ + } } } return NULL; @@ -102,8 +174,14 @@ void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data) for(i = 0 ; i < h->len ; i++) { c = &g_array_index(h, LttvHookClosure, i); if(c->hook == f && c->hook_data == hook_data) { - lttv_hooks_remove_by_position(h, i); - return; + if(c->ref_count == 1) { + lttv_hooks_remove_by_position(h, i); + return; + } else { + g_assert(c->ref_count != 0); + c->ref_count--; + return; + } } } } @@ -120,7 +198,12 @@ void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list) c = &g_array_index(h, LttvHookClosure, i); c_list = &g_array_index(list, LttvHookClosure, j); if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) { - lttv_hooks_remove_by_position(h, i); + if(c->ref_count == 1) { + lttv_hooks_remove_by_position(h, i); + } else { + g_assert(c->ref_count != 0); + c->ref_count--; + } j++; } else i++;