edbus: Refactor edbus_connection_name
authorJosé Roberto de Souza <zehortigoza@profusion.mobi>
Tue, 11 Dec 2012 19:49:46 +0000 (19:49 +0000)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Tue, 11 Dec 2012 19:49:46 +0000 (19:49 +0000)
Simplifications on "monitor" of NameOwnerChanged
Life cycle tied with refcount, objs, and name_owner_changed list.

Patch by: José Roberto de Souza  <zehortigoza@profusion.mobi>

SVN revision: 80684

src/lib/edbus_core.c
src/lib/edbus_private.h
src/lib/edbus_signal_handler.c

index 7a14ed0..f46f050 100644 (file)
@@ -370,42 +370,29 @@ edbus_data_del_all(Eina_Inlist **p_list)
 }
 
 static void
-edbus_connection_name_free(void *data)
+edbus_connection_name_gc(EDBus_Connection *conn, EDBus_Connection_Name *cn)
 {
-   EDBus_Connection_Name *cn = data;
+   Eina_Bool have_obj;
+   Eina_Bool have_event_handlers;
 
-   eina_stringshare_del(cn->name);
-   eina_stringshare_del(cn->unique_id);
+   if (!cn->objects) have_obj = EINA_FALSE;
+   else have_obj = !!eina_hash_population(cn->objects);
+   have_event_handlers = cn->event_handlers.list != NULL;
 
-   if (cn->objects) eina_hash_free(cn->objects);
+   if (have_obj || have_event_handlers || cn->refcount > 0)
+     return;
 
-   while (cn->event_handlers.list)
-     {
-        EDBus_Connection_Context_NOC_Cb *ctx;
-        ctx = EINA_INLIST_CONTAINER_GET(cn->event_handlers.list,
-                                        EDBus_Connection_Context_NOC_Cb);
-        cn->event_handlers.list = eina_inlist_remove(cn->event_handlers.list,
-                                                     cn->event_handlers.list);
-        free(ctx);
-     }
+   eina_hash_del(conn->names, cn->name, cn);
+   if (cn->name_owner_changed)
+     edbus_signal_handler_del(cn->name_owner_changed);
+   if (cn->objects)
+     eina_hash_free(cn->objects);
+   eina_stringshare_del(cn->name);
+   eina_stringshare_del(cn->unique_id);
    eina_list_free(cn->event_handlers.to_delete);
-
    free(cn);
 }
 
-static void
-edbus_connection_name_gc(EDBus_Connection *conn, EDBus_Connection_Name *cn)
-{
-   Eina_Bool no_objs;
-   Eina_Bool no_event_handlers;
-
-   no_objs = ((!cn->objects) || (eina_hash_population(cn->objects) == 0));
-   no_event_handlers = !!cn->event_handlers.list;
-
-   if (no_objs && no_event_handlers && cn->refcount < 1)
-     eina_hash_del(conn->names, cn->name, cn);
-}
-
 void
 edbus_connection_name_object_del(EDBus_Connection *conn, const EDBus_Object *obj)
 {
@@ -427,33 +414,19 @@ edbus_connection_name_object_del(EDBus_Connection *conn, const EDBus_Object *obj
 void
 edbus_connection_name_object_set(EDBus_Connection *conn, EDBus_Object *obj)
 {
-   EDBus_Connection_Name *cn = eina_hash_find(conn->names, obj->name);
-   Eina_Bool had_connection_name = !!cn;
+   EDBus_Connection_Name *cn;
    const EDBus_Connection_Event_Object_Added ev = {
       obj->path,
       obj
    };
 
-   if (!cn)
-     cn = edbus_connection_name_get(conn, obj->name);
-   if (!cn->objects)
-     {
-        cn->objects = eina_hash_string_superfast_new(NULL);
-        EINA_SAFETY_ON_NULL_GOTO(cn->objects, cleanup);
-     }
+   cn = edbus_connection_name_get(conn, obj->name);
    eina_hash_add(cn->objects, obj->path, obj);
 
    _edbus_connection_event_callback_call
      (conn, EDBUS_CONNECTION_EVENT_OBJECT_ADDED, &ev);
 
    return;
-
-cleanup:
-   if (!had_connection_name)
-     {
-        eina_hash_del(conn->names, cn->name, cn);
-        edbus_connection_name_free(cn);
-     }
 }
 
 static void
@@ -468,8 +441,7 @@ on_name_owner_changed(void *data, const EDBus_Message *msg)
         return;
      }
 
-   eina_stringshare_del(cn->unique_id);
-   cn->unique_id = eina_stringshare_add(new_id);
+   eina_stringshare_replace(&cn->unique_id, new_id);
    edbus_dispatch_name_owner_change(cn, older_id);
 }
 
@@ -488,14 +460,15 @@ on_get_name_owner(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
    edbus_dispatch_name_owner_change(cn, NULL);
 }
 
-static void
-_edbus_connection_name_ref(EDBus_Connection *conn, EDBus_Connection_Name *cn)
+void
+edbus_connection_name_ref(EDBus_Connection_Name *cn)
 {
+   EINA_SAFETY_ON_NULL_RETURN(cn);
    cn->refcount++;
 }
 
-static void
-_edbus_connection_name_unref(EDBus_Connection *conn, EDBus_Connection_Name *cn)
+void
+edbus_connection_name_unref(EDBus_Connection *conn, EDBus_Connection_Name *cn)
 {
    EDBUS_CONNECTION_CHECK(conn);
    EINA_SAFETY_ON_NULL_RETURN(cn);
@@ -503,41 +476,9 @@ _edbus_connection_name_unref(EDBus_Connection *conn, EDBus_Connection_Name *cn)
    cn->refcount--;
 
    if (cn->refcount > 0) return;
-   if (cn->name_owner_changed)
-     edbus_signal_handler_del(cn->name_owner_changed);
-   cn->name_owner_changed = NULL;
    edbus_connection_name_gc(conn, cn);
 }
 
-void
-edbus_connection_name_owner_monitor(EDBus_Connection *conn, EDBus_Connection_Name *cn, Eina_Bool enable)
-{
-   EDBUS_CONNECTION_CHECK(conn);
-   EINA_SAFETY_ON_NULL_RETURN(cn);
-
-   if (!enable)
-     {
-        _edbus_connection_name_unref(conn, cn);
-        return;
-     }
-   if (cn->name_owner_changed)
-     {
-        _edbus_connection_name_ref(conn, cn);
-        return;
-     }
-
-   edbus_name_owner_get(conn, cn->name, on_get_name_owner, cn);
-   _edbus_connection_name_ref(conn, cn);
-   cn->name_owner_changed = edbus_signal_handler_add(conn,
-                                              EDBUS_FDO_BUS,
-                                              EDBUS_FDO_PATH,
-                                              EDBUS_FDO_INTERFACE,
-                                              "NameOwnerChanged",
-                                              on_name_owner_changed, cn);
-   edbus_signal_handler_match_extra_set(cn->name_owner_changed, "arg0",
-                                        cn->name, NULL);
-}
-
 EDBus_Connection_Name *
 edbus_connection_name_get(EDBus_Connection *conn, const char *name)
 {
@@ -550,7 +491,23 @@ edbus_connection_name_get(EDBus_Connection *conn, const char *name)
    cn = calloc(1, sizeof(EDBus_Connection_Name));
    EINA_SAFETY_ON_NULL_RETURN_VAL(cn, NULL);
    cn->name = eina_stringshare_add(name);
+   cn->objects = eina_hash_string_superfast_new(NULL);
 
+   if (name[0] == ':' || !strcmp(name, EDBUS_FDO_BUS))
+     {
+        cn->unique_id = eina_stringshare_add(name);
+        goto end;
+     }
+   edbus_name_owner_get(conn, cn->name, on_get_name_owner, cn);
+   cn->name_owner_changed = edbus_signal_handler_add(conn, EDBUS_FDO_BUS,
+                                                     EDBUS_FDO_PATH,
+                                                     EDBUS_FDO_INTERFACE,
+                                                     "NameOwnerChanged",
+                                                     on_name_owner_changed, cn);
+   edbus_signal_handler_match_extra_set(cn->name_owner_changed, "arg0",
+                                        cn->name, NULL);
+
+end:
    eina_hash_direct_add(conn->names, cn->name, cn);
    return cn;
 }
@@ -1000,7 +957,7 @@ edbus_connection_get(EDBus_Connection_Type type)
    conn->refcount = 1;
    EINA_MAGIC_SET(conn, EDBUS_CONNECTION_MAGIC);
 
-   conn->names = eina_hash_string_superfast_new(edbus_connection_name_free);
+   conn->names = eina_hash_string_superfast_new(NULL);
 
    DBG("Returned new connection at %p", conn);
    return conn;
@@ -1024,9 +981,11 @@ _edbus_connection_unref(EDBus_Connection *conn)
    Eina_Inlist *list;
    EDBus_Signal_Handler *h;
    EDBus_Pending *p;
+   Eina_Iterator *iter;
+   EDBus_Connection_Name *cn;
 
    DBG("Connection %p: unref (currently at %d refs)",
-      conn, conn->refcount);
+       conn, conn->refcount);
 
    if (--conn->refcount > 0) return;
 
@@ -1047,6 +1006,24 @@ _edbus_connection_unref(EDBus_Connection *conn)
         h = EINA_INLIST_CONTAINER_GET(conn->signal_handlers, EDBus_Signal_Handler);
         edbus_signal_handler_del(h);
      }
+
+   iter = eina_hash_iterator_data_new(conn->names);
+   EINA_ITERATOR_FOREACH(iter, cn)
+     {
+        while (cn->event_handlers.list)
+          {
+             EDBus_Connection_Context_NOC_Cb *ctx;
+             ctx = EINA_INLIST_CONTAINER_GET(cn->event_handlers.list,
+                                             EDBus_Connection_Context_NOC_Cb);
+             cn->event_handlers.list = eina_inlist_remove(cn->event_handlers.list,
+                                                          cn->event_handlers.list);
+             free(ctx);
+           }
+        edbus_connection_name_gc(conn, cn);
+     }
+   eina_iterator_free(iter);
+   eina_hash_free(conn->names);
+
    conn->refcount = 0;
 
    /* after cbs_free dispatch these shouldn't exit, error if they do */
@@ -1054,7 +1031,7 @@ _edbus_connection_unref(EDBus_Connection *conn)
    if (conn->pendings)
      {
         CRITICAL("Connection %p released with live pending calls!",
-                conn);
+                 conn);
         EINA_INLIST_FOREACH(conn->pendings, p)
           ERR("conn=%p alive pending call=%p dest=%s path=%s %s.%s()",
               conn, p,
@@ -1078,8 +1055,6 @@ _edbus_connection_unref(EDBus_Connection *conn)
         eina_list_free(ce->to_delete);
      }
 
-   eina_hash_free(conn->names);
-
    EINA_MAGIC_SET(conn, EINA_MAGIC_NONE);
    dbus_connection_close(conn->dbus_conn);
    dbus_connection_unref(conn->dbus_conn);
@@ -1193,8 +1168,6 @@ edbus_name_owner_changed_callback_add(EDBus_Connection *conn, const char *bus, E
 
    cn = edbus_connection_name_get(conn, bus);
    EINA_SAFETY_ON_NULL_RETURN(cn);
-   edbus_connection_name_owner_monitor(conn, cn, EINA_TRUE);
-
    ctx = calloc(1, sizeof(EDBus_Connection_Context_NOC_Cb));
    EINA_SAFETY_ON_NULL_GOTO(ctx, cleanup);
    ctx->cb = cb;
@@ -1215,7 +1188,7 @@ edbus_name_owner_changed_callback_add(EDBus_Connection *conn, const char *bus, E
    return;
 
 cleanup:
-   _edbus_connection_name_unref(conn, cn);
+   edbus_connection_name_gc(conn, cn);
 }
 
 EAPI void
@@ -1260,7 +1233,6 @@ edbus_name_owner_changed_callback_del(EDBus_Connection *conn, const char *bus, E
         free(data);
      }
    free(found);
-   edbus_connection_name_owner_monitor(conn, cn, EINA_FALSE);
 }
 
 EAPI void
index 1e10bfa..41adc17 100644 (file)
@@ -75,6 +75,9 @@ EDBus_Pending         *_edbus_connection_send(EDBus_Connection *conn, EDBus_Mess
 EDBus_Message_Iter    *edbus_message_iter_sub_iter_get(EDBus_Message_Iter *iter);
 Eina_Value            *_message_iter_struct_to_eina_value(EDBus_Message_Iter *iter);
 
+void                   edbus_connection_name_ref(EDBus_Connection_Name *cn);
+void                   edbus_connection_name_unref(EDBus_Connection *conn, EDBus_Connection_Name *cn);
+
 #ifdef HAVE_VA_LIST_AS_ARRAY
 #define MAKE_PTR_FROM_VA_LIST(arg) ((va_list *)(arg))
 #else
index ec45adf..af3600d 100644 (file)
@@ -175,11 +175,11 @@ edbus_signal_handler_add(EDBus_Connection *conn, const char *sender, const char
    dbus_bus_add_match(conn->dbus_conn, eina_strbuf_string_get(match), &err);
    if (dbus_error_is_set(&err)) goto cleanup;
 
-   if (sender && sender[0] != ':' && strcmp(sender, EDBUS_FDO_BUS))
+   if (sender)
      {
         sh->bus = edbus_connection_name_get(conn, sender);
         if (!sh->bus) goto cleanup;
-        edbus_connection_name_owner_monitor(conn, sh->bus, EINA_TRUE);
+        edbus_connection_name_ref(sh->bus);
      }
 
    sh->cb = cb;
@@ -243,6 +243,9 @@ _edbus_signal_handler_del(EDBus_Signal_Handler *handler)
         free(arg);
      }
    eina_inlist_sorted_state_free(handler->state_args);
+
+   if (handler->bus)
+     edbus_connection_name_unref(handler->conn, handler->bus);
    free(handler);
 }