From aab45618cc12799d5f7351ef8832ae73b33057c7 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Fri, 26 Jul 2013 13:45:16 -0400 Subject: [PATCH 2/8] 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 0d74413..9168b8a 100644 --- a/server/red_channel.c +++ b/server/red_channel.c @@ -1932,10 +1932,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) { @@ -2012,9 +2031,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 -- 1.8.3.1