X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fhook.c;h=9f08b98b46f1ed4e0b6d694f927e89f0da127f1a;hb=bc8d270bb296f985deb9e37e29e41d445daaac28;hp=183f499a46fd7065ce32c62330e6259470deb88e;hpb=bb545b3cec36359286807096eef91175d1dd5da4;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/hook.c b/ltt/branches/poly/lttv/lttv/hook.c index 183f499a..9f08b98b 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) @@ -57,8 +58,21 @@ void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p) 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); @@ -81,25 +95,44 @@ void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p) */ void lttv_hooks_add_list(LttvHooks *h, const LttvHooks *list) { - guint i,j; + guint i,j,k; LttvHookClosure *c; const LttvHookClosure *new_c; if(list == NULL) return; for(i = 0, j = 0 ; i < list->len; i++) { new_c = &g_array_index(list, LttvHookClosure, i); - 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++; + 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; } - else j++; } - if(j == h->len) { - g_array_append_val(h,*new_c); - j++; + + 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++; + } } } } @@ -116,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; @@ -134,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; + } } } } @@ -152,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++; @@ -242,42 +293,42 @@ gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1, guint i, j; - if(h1 != NULL && h2 != NULL) { - for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { - c1 = &g_array_index(h1, LttvHookClosure, i); - c2 = &g_array_index(h2, LttvHookClosure, j); - if(c1->prio <= c2->prio) { + if(h1 != NULL) { + if(h2 != NULL) { + for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { + c1 = &g_array_index(h1, LttvHookClosure, i); + c2 = &g_array_index(h2, LttvHookClosure, j); + if(c1->prio <= c2->prio) { + ret = c1->hook(c1->hook_data,call_data1); + sum_ret = sum_ret || ret; + i++; + } + else { + ret = c2->hook(c2->hook_data,call_data2); + sum_ret = sum_ret || ret; + j++; + } + } + /* Finish the last list with hooks left */ + for(;i < h1->len; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); ret = c1->hook(c1->hook_data,call_data1); sum_ret = sum_ret || ret; - i++; } - else { + for(;j < h2->len; j++) { + c2 = &g_array_index(h2, LttvHookClosure, j); ret = c2->hook(c2->hook_data,call_data2); sum_ret = sum_ret || ret; - j++; + } + } else { /* h1 != NULL && h2 == NULL */ + for(i = 0 ; i < h1->len ; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); + ret = c1->hook(c1->hook_data,call_data1); + sum_ret = sum_ret || ret; } } - /* Finish the last list with hooks left */ - for(;i < h1->len; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - ret = c1->hook(c1->hook_data,call_data1); - sum_ret = sum_ret || ret; - } - for(;j < h2->len; j++) { - c2 = &g_array_index(h2, LttvHookClosure, j); - ret = c2->hook(c2->hook_data,call_data2); - sum_ret = sum_ret || ret; - } - } - else if(h1 != NULL && h2 == NULL) { - for(i = 0 ; i < h1->len ; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - ret = c1->hook(c1->hook_data,call_data1); - sum_ret = sum_ret || ret; - } - } - else if(h1 == NULL && h2 != NULL) { - for(j = 0 ; j < h2->len ; j++) { + } else if(h2 != NULL) { /* h1 == NULL && h2 != NULL */ + for(j = 0 ; j < h2->len ; j++) { c2 = &g_array_index(h2, LttvHookClosure, j); ret = c2->hook(c2->hook_data,call_data2); sum_ret = sum_ret || ret; @@ -294,42 +345,42 @@ gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1, guint i, j; - if(h1 != NULL && h2 != NULL) { - for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { - c1 = &g_array_index(h1, LttvHookClosure, i); - c2 = &g_array_index(h2, LttvHookClosure, j); - if(c1->prio <= c2->prio) { + if(h1 != NULL) { + if(h2 != NULL) { + for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { + c1 = &g_array_index(h1, LttvHookClosure, i); + c2 = &g_array_index(h2, LttvHookClosure, j); + if(c1->prio <= c2->prio) { + if(c1->hook(c1->hook_data,call_data1)) return TRUE; + i++; + } + else { + if(c2->hook(c2->hook_data,call_data2)) return TRUE; + j++; + } + } + /* Finish the last list with hooks left */ + for(;i < h1->len; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); if(c1->hook(c1->hook_data,call_data1)) return TRUE; - i++; } - else { + for(;j < h2->len; j++) { + c2 = &g_array_index(h2, LttvHookClosure, j); if(c2->hook(c2->hook_data,call_data2)) return TRUE; - j++; + } + } else { /* h2 == NULL && h1 != NULL */ + for(i = 0 ; i < h1->len ; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); + if(c1->hook(c1->hook_data,call_data1)) return TRUE; } } - /* Finish the last list with hooks left */ - for(;i < h1->len; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - if(c1->hook(c1->hook_data,call_data1)) return TRUE; - } - for(;j < h2->len; j++) { - c2 = &g_array_index(h2, LttvHookClosure, j); - if(c2->hook(c2->hook_data,call_data2)) return TRUE; - } - } - else if(h1 != NULL && h2 == NULL) { - for(i = 0 ; i < h1->len ; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - if(c1->hook(c1->hook_data,call_data1)) return TRUE; - } - } - else if(h1 == NULL && h2 != NULL) { + } else if(h2 != NULL) { /* h1 == NULL && h2 != NULL */ for(j = 0 ; j < h2->len ; j++) { c2 = &g_array_index(h2, LttvHookClosure, j); if(c2->hook(c2->hook_data,call_data2)) return TRUE; } } - + return FALSE; } @@ -365,14 +416,6 @@ unsigned lttv_hooks_by_id_max_id(LttvHooksById *h) return h->len; } - -LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id) -{ - if(id < h->len) return h->pdata[id]; - return NULL; -} - - void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id) { if(id < h->len && h->pdata[id] != NULL) {