edbus: Refactor edbus_connection_name

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
This commit is contained in:
José Roberto de Souza 2012-12-11 19:49:46 +00:00 committed by Lucas De Marchi
parent d5dab6de7b
commit 4327109500
3 changed files with 73 additions and 95 deletions

View File

@ -369,41 +369,28 @@ edbus_data_del_all(Eina_Inlist **p_list)
}
}
static void
edbus_connection_name_free(void *data)
{
EDBus_Connection_Name *cn = data;
eina_stringshare_del(cn->name);
eina_stringshare_del(cn->unique_id);
if (cn->objects) eina_hash_free(cn->objects);
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_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;
Eina_Bool have_obj;
Eina_Bool have_event_handlers;
no_objs = ((!cn->objects) || (eina_hash_population(cn->objects) == 0));
no_event_handlers = !!cn->event_handlers.list;
if (!cn->objects) have_obj = EINA_FALSE;
else have_obj = !!eina_hash_population(cn->objects);
have_event_handlers = cn->event_handlers.list != NULL;
if (no_objs && no_event_handlers && cn->refcount < 1)
eina_hash_del(conn->names, cn->name, cn);
if (have_obj || have_event_handlers || cn->refcount > 0)
return;
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);
}
void
@ -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

View 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

View 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);
}