typedef struct _LttvHookClosure {
- LttvHook hook;
- void *hook_data;
+ LttvHook hook;
+ void *hook_data;
+ LttvHookPrio prio;
} LttvHookClosure;
+gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b)
+{
+ if(a->prio < b->prio) return -1;
+ if(a->prio > b->prio) return 1;
+ return 0;
+}
+
LttvHooks *lttv_hooks_new()
{
}
-void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data)
+void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p)
{
LttvHookClosure c;
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);
}
for(i = 0 ; i < list->len; i++) {
g_array_append_val(h,g_array_index(list, LttvHookClosure, i));
}
+ g_array_sort(h, (GCompareFunc)lttv_hooks_prio_compare);
}
}
-void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data)
+void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
+ LttvHookPrio *p)
{
LttvHookClosure *c;
+ if(i >= h->len)
+ {
+ *f = NULL;
+ *hook_data = NULL;
+ *p = 0;
+ return;
+ }
+
c = &g_array_index(h, LttvHookClosure, i);
*f = c->hook;
*hook_data = c->hook_data;
+ *p = c->prio;
}
g_array_remove_index(h, i);
}
-
gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
{
gboolean ret, sum_ret = FALSE;
return FALSE;
}
+gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1,
+ LttvHooks *h2, void *call_data2)
+{
+ gboolean ret, sum_ret = FALSE;
+
+ LttvHookClosure *c1, *c2;
+
+ 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) {
+ 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;
+ }
+ 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++) {
+ c2 = &g_array_index(h2, LttvHookClosure, j);
+ ret = c2->hook(c2->hook_data,call_data2);
+ sum_ret = sum_ret || ret;
+ }
+ }
+
+ return sum_ret;
+}
+
+gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1,
+ LttvHooks *h2, void *call_data2)
+{
+ LttvHookClosure *c1, *c2;
+
+ 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(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;
+ }
+ 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) {
+ 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;
+
+}
+
LttvHooksById *lttv_hooks_by_id_new()
{
/* This file is part of the Linux Trace Toolkit viewer
* Copyright (C) 2003-2004 Michel Dagenais
*
+ * 25/05/2004 Mathieu Desnoyers : Hook priorities
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 2 as
* published by the Free Software Foundation;
typedef GArray LttvHooks;
+/* A priority associated with each hook, from -19 (high prio) to 20 (low prio)
+ * 0 being the default priority.
+ *
+ * Priority ordering is done in the lttv_hooks_add and lttv_hooks_add_list
+ * functions. Hook removal does not change list order.
+ */
+
+#define LTTV_PRIO_DEFAULT 0
+typedef gint LttvHookPrio;
/* Create and destroy a list of hooks */
/* Add a hook and its hook data to the list */
-void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data);
+void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p);
/* Add a list of hooks to the list h */
/* Remove a list of hooks from the hooks list in h. */
-void lttv_hooks_remove_data_list(LttvHooks *h, LttvHook *list);
+void lttv_hooks_remove_data_list(LttvHooks *h, LttvHooks *list);
/* Return the number of hooks in the list */
unsigned lttv_hooks_number(LttvHooks *h);
-/* Return the hook at the specified position in the list */
+/* Return the hook at the specified position in the list.
+ * *f and *hook_data are NULL if no hook exists at that position. */
-void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data);
+void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
+ LttvHookPrio *p);
/* Remove the specified hook. The position of the following hooks may change */
/* Call all the hooks in the list, each with its hook data,
- with the specified call data. Return TRUE if one hook returned TRUE. */
+ with the specified call data, in priority order. Return TRUE if one hook
+ returned TRUE. */
gboolean lttv_hooks_call(LttvHooks *h, void *call_data);
-/* Call the hooks in the list until one returns true, in which case TRUE is
- returned. */
+/* Call the hooks in the list in priority order until one returns true,
+ * in which case TRUE is returned. */
gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data);
+/* Call hooks from two lists in priority order. If priority is the same,
+ * hooks from h1 are called first. */
+
+gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1,
+ LttvHooks *h2, void *call_data2);
+
+gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1,
+ LttvHooks *h2, void *call_data2);
+
/* Sometimes different hooks need to be called based on the case. The
case is represented by an unsigned integer id */