From 2b9e1dcd5509dd2931e070f397adf5d2abcfa005 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Mon, 9 Mar 2020 02:25:03 +0000 Subject: [PATCH] dispatcher: Reuse base reference counting for Dispatcher hierararchy Signed-off-by: Frediano Ziglio --- server/dispatcher.h | 7 +------ server/red-channel.cpp | 15 ++++++--------- server/red-qxl.cpp | 14 +++++++------- server/reds-private.h | 2 +- server/reds.cpp | 8 +++----- 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/server/dispatcher.h b/server/dispatcher.h index db1c45f8..232d9a92 100644 --- a/server/dispatcher.h +++ b/server/dispatcher.h @@ -52,10 +52,9 @@ typedef void (*dispatcher_handle_any_message)(void *opaque, * activity and should call dispatcher_handle_recv_read() to process incoming * messages. */ -class Dispatcher +class Dispatcher: public red::shared_ptr_counted { public: - SPICE_CXX_GLIB_ALLOCATOR /* Create a new Dispatcher object * * @max_message_type: indicates the number of unique message types that can @@ -150,9 +149,6 @@ public: */ void set_opaque(void *opaque); - void ref() { g_atomic_int_inc(&_ref); } - void unref() { if (g_atomic_int_dec_and_test(&_ref)) delete this; } - protected: virtual ~Dispatcher(); @@ -160,7 +156,6 @@ private: static int handle_single_read(Dispatcher *dispatcher); static void handle_event(int fd, int event, Dispatcher* dispatcher); void send_message_internal(const DispatcherMessage*msg, void *payload); - gint _ref = 1; red::unique_link priv; }; diff --git a/server/red-channel.cpp b/server/red-channel.cpp index 2e2925ef..5d60096d 100644 --- a/server/red-channel.cpp +++ b/server/red-channel.cpp @@ -72,7 +72,7 @@ struct RedChannelPrivate handle_acks(!!(flags & RedChannel::HandleAcks)), parser(spice_get_client_channel_parser(type, nullptr)), migration_flags(flags & RedChannel::MigrateAll), - dispatcher(red::add_ref(dispatcher)), + dispatcher(dispatcher), reds(reds) { thread_id = pthread_self(); @@ -80,9 +80,6 @@ struct RedChannelPrivate ~RedChannelPrivate() { - if (dispatcher) { - dispatcher->unref(); - } red_channel_capabilities_reset(&local_caps); } @@ -118,7 +115,7 @@ struct RedChannelPrivate * thread_id will be used to check the channel thread and automatically * use the dispatcher if the thread is different. */ - Dispatcher *const dispatcher; + const red::shared_ptr dispatcher; RedsState *const reds; RedStatNode stat; }; @@ -351,13 +348,13 @@ static void handle_dispatcher_connect(void *opaque, RedMessageConnect *msg) void RedChannel::connect(RedClient *client, RedStream *stream, int migration, RedChannelCapabilities *caps) { - if (priv->dispatcher == NULL || + if (!priv->dispatcher || pthread_equal(pthread_self(), priv->thread_id)) { on_connect(client, stream, migration, caps); return; } - Dispatcher *dispatcher = priv->dispatcher; + Dispatcher *dispatcher = priv->dispatcher.get(); // get a reference potentially the main channel can be destroyed in // the main thread causing RedClient to be destroyed before using it @@ -560,7 +557,7 @@ static void handle_dispatcher_migrate(void *opaque, RedMessageMigrate *msg) void RedChannel::migrate_client(RedChannelClient *rcc) { - if (priv->dispatcher == NULL || + if (!priv->dispatcher || pthread_equal(pthread_self(), priv->thread_id)) { rcc->migrate(); return; @@ -584,7 +581,7 @@ static void handle_dispatcher_disconnect(void *opaque, RedMessageDisconnect *msg void RedChannel::disconnect_client(RedChannelClient *rcc) { - if (priv->dispatcher == NULL || + if (!priv->dispatcher || pthread_equal(pthread_self(), priv->thread_id)) { rcc->disconnect(); return; diff --git a/server/red-qxl.cpp b/server/red-qxl.cpp index 8ca0273a..ef84b5ae 100644 --- a/server/red-qxl.cpp +++ b/server/red-qxl.cpp @@ -42,8 +42,9 @@ #define MAX_MONITORS_COUNT 16 struct QXLState { + SPICE_CXX_GLIB_ALLOCATOR QXLInstance *qxl; - Dispatcher *dispatcher; + red::shared_ptr dispatcher; uint32_t pending; int primary_active; int x_res; @@ -566,13 +567,13 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl) spice_return_if_fail(qxl != NULL); - qxl_state = g_new0(QXLState, 1); + qxl_state = new QXLState(); qxl_state->reds = reds; qxl_state->qxl = qxl; pthread_mutex_init(&qxl_state->scanout_mutex, NULL); qxl_state->scanout.drm_dma_buf_fd = -1; qxl_state->gl_draw_cookie = GL_DRAW_COOKIE_INVALID; - qxl_state->dispatcher = new Dispatcher(RED_WORKER_MESSAGE_COUNT); + qxl_state->dispatcher = red::make_shared(RED_WORKER_MESSAGE_COUNT); qxl_state->max_monitors = UINT_MAX; qxl->st = qxl_state; @@ -584,7 +585,7 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl) void red_qxl_destroy(QXLInstance *qxl) { - spice_return_if_fail(qxl->st != NULL && qxl->st->dispatcher != NULL); + spice_return_if_fail(qxl->st != NULL && qxl->st->dispatcher); QXLState *qxl_state = qxl->st; @@ -592,16 +593,15 @@ void red_qxl_destroy(QXLInstance *qxl) RedWorkerMessageClose message; qxl_state->dispatcher->send_message(RED_WORKER_MESSAGE_CLOSE_WORKER, &message); red_worker_free(qxl_state->worker); - qxl_state->dispatcher->unref(); /* this must be done after calling red_worker_free */ qxl->st = NULL; pthread_mutex_destroy(&qxl_state->scanout_mutex); - g_free(qxl_state); + delete qxl_state; } Dispatcher *red_qxl_get_dispatcher(QXLInstance *qxl) { - return qxl->st->dispatcher; + return qxl->st->dispatcher.get(); } void red_qxl_clear_pending(QXLState *qxl_state, int pending) diff --git a/server/reds-private.h b/server/reds-private.h index 8fbfda6d..1cb50239 100644 --- a/server/reds-private.h +++ b/server/reds-private.h @@ -135,7 +135,7 @@ struct RedsState { SpiceCoreInterfaceInternal core; red::safe_list qxl_instances; // XXX owning - MainDispatcher *main_dispatcher; + red::shared_ptr main_dispatcher; RedRecord *record; }; diff --git a/server/reds.cpp b/server/reds.cpp index 4e40e52f..a9b88e11 100644 --- a/server/reds.cpp +++ b/server/reds.cpp @@ -3428,7 +3428,7 @@ static int do_spice_init(RedsState *reds, SpiceCoreInterface *core_interface) reds->core.public_interface = core_interface; reds->agent_dev = red_char_device_vdi_port_new(reds); reds_update_agent_properties(reds); - reds->main_dispatcher = new MainDispatcher(reds); + reds->main_dispatcher = red::make_shared(reds); reds->mig_target_clients = NULL; reds->vm_running = TRUE; /* for backward compatibility */ @@ -3795,9 +3795,7 @@ SPICE_GNUC_VISIBLE void spice_server_destroy(SpiceServer *reds) SSL_CTX_free(reds->ctx); } - if (reds->main_dispatcher) { - reds->main_dispatcher->unref(); - } + reds->main_dispatcher.reset(); reds_cleanup_net(reds); if (reds->agent_dev) { reds->agent_dev->unref(); @@ -4489,7 +4487,7 @@ uint32_t reds_qxl_ram_size(RedsState *reds) MainDispatcher* reds_get_main_dispatcher(RedsState *reds) { - return reds->main_dispatcher; + return reds->main_dispatcher.get(); } static void red_char_device_vdi_port_constructed(GObject *object)