This will be used on asynchronous call. E.g. DBus call Connect() etc...
---
 include/peer.h | 12 +++++++++-
 plugins/wifi.c |  4 +++-
 src/peer.c     | 71 +++++++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/include/peer.h b/include/peer.h
index 5c1d1ec..674cc3e 100644
--- a/include/peer.h
+++ b/include/peer.h
@@ -29,7 +29,17 @@ extern "C" {
 struct connman_peer;
 
 struct connman_peer *connman_peer_create(const char *identifier);
-void connman_peer_destroy(struct connman_peer *peer);
+
+#define connman_peer_ref(peer) \
+       connman_peer_ref_debug(peer, __FILE__, __LINE__, __func__)
+
+#define connman_peer_unref(peer) \
+       connman_peer_unref_debug(peer, __FILE__, __LINE__, __func__)
+
+struct connman_peer *connman_peer_ref_debug(struct connman_peer *peer,
+                       const char *file, int line, const char *caller);
+void connman_peer_unref_debug(struct connman_peer *peer,
+                       const char *file, int line, const char *caller);
 
 const char *connman_peer_get_identifier(struct connman_peer *peer);
 void connman_peer_set_name(struct connman_peer *peer, const char *name);
diff --git a/plugins/wifi.c b/plugins/wifi.c
index c8d0bcd..48a9cf3 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -2109,8 +2109,10 @@ static void peer_lost(GSupplicantPeer *peer)
        DBG("ident: %s", identifier);
 
        connman_peer = connman_peer_get(wifi->device, identifier);
-       if (connman_peer)
+       if (connman_peer) {
                connman_peer_unregister(connman_peer);
+               connman_peer_unref(connman_peer);
+       }
 }
 
 static void debug(const char *str)
diff --git a/src/peer.c b/src/peer.c
index a8a459a..145ab78 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -35,16 +35,34 @@ static GHashTable *peers_table = NULL;
 static struct connman_peer_driver *peer_driver;
 
 struct connman_peer {
+       int refcount;
        struct connman_device *device;
        char *identifier;
        char *name;
        char *path;
+       bool registered;
 };
 
 static void peer_free(gpointer data)
 {
        struct connman_peer *peer = data;
-       connman_peer_destroy(peer);
+
+       connman_peer_unregister(peer);
+
+       if (peer->path) {
+               g_free(peer->path);
+               peer->path = NULL;
+       }
+
+       if (peer->device) {
+               connman_device_unref(peer->device);
+               peer->device = NULL;
+       }
+
+       g_free(peer->identifier);
+       g_free(peer->name);
+
+       g_free(peer);
 }
 
 static void append_properties(DBusMessageIter *iter, struct connman_peer *peer)
@@ -205,28 +223,35 @@ struct connman_peer *connman_peer_create(const char 
*identifier)
        peer = g_malloc0(sizeof(struct connman_peer));
        peer->identifier = g_strdup(identifier);
 
+       peer->refcount = 1;
+
        return peer;
 }
 
-void connman_peer_destroy(struct connman_peer *peer)
+struct connman_peer *connman_peer_ref_debug(struct connman_peer *peer,
+                               const char *file, int line, const char *caller)
 {
-       if (!peer)
-               return;
+       DBG("%p ref %d by %s:%d:%s()", peer, peer->refcount + 1,
+                                               file, line, caller);
 
-       if (peer->path) {
-               peer_removed(peer);
-               g_dbus_unregister_interface(connection, peer->path,
-                                               CONNMAN_PEER_INTERFACE);
-               g_free(peer->path);
-       }
+       __sync_fetch_and_add(&peer->refcount, 1);
 
-       if (peer->device)
-               connman_device_unref(peer->device);
+       return peer;
+}
 
-       g_free(peer->identifier);
-       g_free(peer->name);
+void connman_peer_unref_debug(struct connman_peer *peer,
+                               const char *file, int line, const char *caller)
+{
+       DBG("%p ref %d by %s:%d:%s()", peer, peer->refcount - 1,
+                                               file, line, caller);
 
-       g_free(peer);
+       if (__sync_fetch_and_sub(&peer->refcount, 1) != 1)
+               return;
+
+       if (!peer->registered && !peer->path)
+               return peer_free(peer);
+
+       g_hash_table_remove(peers_table, peer->path);
 }
 
 const char *connman_peer_get_identifier(struct connman_peer *peer)
@@ -287,7 +312,7 @@ int connman_peer_register(struct connman_peer *peer)
 {
        DBG("peer %p", peer);
 
-       if (peer->path)
+       if (peer->path && peer->registered)
                return -EALREADY;
 
        peer->path = get_peer_path(peer->device, peer->identifier);
@@ -299,6 +324,7 @@ int connman_peer_register(struct connman_peer *peer)
                                        CONNMAN_PEER_INTERFACE,
                                        peer_methods, peer_signals,
                                        NULL, peer, NULL);
+       peer->registered = true;
        peer_added(peer);
 
        return 0;
@@ -308,10 +334,13 @@ void connman_peer_unregister(struct connman_peer *peer)
 {
        DBG("peer %p", peer);
 
-       if (peer->path)
-               g_hash_table_remove(peers_table, peer->path);
-       else
-               connman_peer_destroy(peer);
+       if (!peer->path || !peer->registered)
+               return;
+
+       g_dbus_unregister_interface(connection, peer->path,
+                                       CONNMAN_PEER_INTERFACE);
+       peer->registered = false;
+       peer_removed(peer);
 }
 
 struct connman_peer *connman_peer_get(struct connman_device *device,
@@ -370,5 +399,7 @@ void __connman_peer_cleanup(void)
        DBG("");
 
        g_hash_table_destroy(peers_table);
+       peers_table = NULL;
        dbus_connection_unref(connection);
+       connection = NULL;
 }
-- 
1.8.5.5

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to