Add function to unregister all children of an element
authorMarcel Holtmann <marcel@holtmann.org>
Sun, 10 Aug 2008 09:56:25 +0000 (11:56 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Sun, 10 Aug 2008 09:56:25 +0000 (11:56 +0200)
include/element.h
src/element.c

index fb4f70f..c0702ac 100644 (file)
@@ -119,6 +119,7 @@ extern int connman_element_get_value(struct connman_element *element,
 extern int connman_element_register(struct connman_element *element,
                                        struct connman_element *parent);
 extern void connman_element_unregister(struct connman_element *element);
+extern void connman_element_unregister_children(struct connman_element *element);
 extern void connman_element_update(struct connman_element *element);
 
 static inline void *connman_element_get_data(struct connman_element *element)
index 5e1bea5..790d615 100644 (file)
@@ -39,6 +39,7 @@ static GSList *driver_list = NULL;
 
 static GThreadPool *thread_register = NULL;
 static GThreadPool *thread_unregister = NULL;
+static GThreadPool *thread_unregister_children = NULL;
 
 static gchar *device_filter = NULL;
 
@@ -647,6 +648,14 @@ void connman_element_unregister(struct connman_element *element)
                g_thread_pool_push(thread_unregister, element, NULL);
 }
 
+void connman_element_unregister_children(struct connman_element *element)
+{
+       DBG("element %p name %s", element, element->name);
+
+       if (thread_unregister_children != NULL)
+               g_thread_pool_push(thread_unregister_children, element, NULL);
+}
+
 void connman_element_update(struct connman_element *element)
 {
        DBG("element %p name %s", element, element->name);
@@ -734,9 +743,13 @@ static void register_element(gpointer data, gpointer user_data)
 static gboolean remove_element(GNode *node, gpointer user_data)
 {
        struct connman_element *element = node->data;
+       struct connman_element *root = user_data;
 
        DBG("element %p name %s", element, element->name);
 
+       if (element == root)
+               return FALSE;
+
        if (element->driver) {
                if (element->driver->remove)
                        element->driver->remove(element);
@@ -782,6 +795,24 @@ static void unregister_element(gpointer data, gpointer user_data)
        g_static_rw_lock_writer_unlock(&element_lock);
 }
 
+static void unregister_children(gpointer data, gpointer user_data)
+{
+       struct connman_element *element = data;
+       GNode *node;
+
+       DBG("element %p name %s", element, element->name);
+
+       g_static_rw_lock_writer_lock(&element_lock);
+
+       node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
+
+       if (node != NULL)
+               g_node_traverse(node, G_POST_ORDER,
+                               G_TRAVERSE_ALL, -1, remove_element, element);
+
+       g_static_rw_lock_writer_unlock(&element_lock);
+}
+
 int __connman_element_init(DBusConnection *conn, const char *device)
 {
        struct connman_element *element;
@@ -810,6 +841,8 @@ int __connman_element_init(DBusConnection *conn, const char *device)
                                                        NULL, 1, FALSE, NULL);
        thread_unregister = g_thread_pool_new(unregister_element,
                                                        NULL, 1, FALSE, NULL);
+       thread_unregister_children = g_thread_pool_new(unregister_children,
+                                                       NULL, 1, FALSE, NULL);
 
        return 0;
 }
@@ -864,6 +897,9 @@ void __connman_element_cleanup(void)
        g_thread_pool_free(thread_unregister, FALSE, TRUE);
        thread_unregister = NULL;
 
+       g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
+       thread_unregister_children = NULL;
+
        g_static_rw_lock_writer_lock(&element_lock);
        g_node_destroy(element_root);
        element_root = NULL;