draw closure in cfv optimisation
[lttv.git] / ltt / branches / poly / lttv / lttv / hook.c
index 183f499a46fd7065ce32c62330e6259470deb88e..9f08b98b46f1ed4e0b6d694f927e89f0da127f1a 100644 (file)
@@ -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) {
This page took 0.026452 seconds and 4 git commands to generate.