Blob Blame History Raw
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yonit Halperin <yhalperi@redhat.com>
Date: Fri, 26 Jul 2013 13:45:16 -0400
Subject: [PATCH] red_channel: add ref count to RedClient

---
 server/red_channel.c | 23 ++++++++++++++++++++---
 server/red_channel.h | 17 +++++++++++++++--
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/server/red_channel.c b/server/red_channel.c
index fa4db7b..9433bef 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -1920,10 +1920,29 @@ RedClient *red_client_new(int migrated)
     pthread_mutex_init(&client->lock, NULL);
     client->thread_id = pthread_self();
     client->during_target_migrate = migrated;
+    client->refs = 1;
 
     return client;
 }
 
+RedClient *red_client_ref(RedClient *client)
+{
+    spice_assert(client);
+    client->refs++;
+    return client;
+}
+
+RedClient *red_client_unref(RedClient *client)
+{
+    if (!--client->refs) {
+        spice_debug("release client=%p", client);
+        pthread_mutex_destroy(&client->lock);
+        free(client);
+        return NULL;
+    }
+    return client;
+}
+
 /* client mutex should be locked before this call */
 static void red_channel_client_set_migration_seamless(RedChannelClient *rcc)
 {
@@ -2000,9 +2019,7 @@ void red_client_destroy(RedClient *client)
         spice_assert(rcc->send_data.size == 0);
         red_channel_client_destroy(rcc);
     }
-
-    pthread_mutex_destroy(&client->lock);
-    free(client);
+    red_client_unref(client);
 }
 
 /* client->lock should be locked */
diff --git a/server/red_channel.h b/server/red_channel.h
index ba299b6..0dd73ea 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -561,10 +561,25 @@ struct RedClient {
                                   is called */
     int seamless_migrate;
     int num_migrated_channels; /* for seamless - number of channels that wait for migrate data*/
+    int refs;
 };
 
 RedClient *red_client_new(int migrated);
 
+/*
+ * disconnects all the client's channels (should be called from the client's thread)
+ */
+void red_client_destroy(RedClient *client);
+
+RedClient *red_client_ref(RedClient *client);
+
+/*
+ * releases the client resources when refs == 0.
+ * We assume the red_client_derstroy was called before
+ * we reached refs==0
+ */
+RedClient *red_client_unref(RedClient *client);
+
 MainChannelClient *red_client_get_main(RedClient *client);
 // main should be set once before all the other channels are created
 void red_client_set_main(RedClient *client, MainChannelClient *mcc);
@@ -580,7 +595,5 @@ void red_client_semi_seamless_migrate_complete(RedClient *client); /* dst side *
 int red_client_during_migrate_at_target(RedClient *client);
 
 void red_client_migrate(RedClient *client);
-// disconnects all the client's channels (should be called from the client's thread)
-void red_client_destroy(RedClient *client);
 
 #endif