dispatcher: Reuse base reference counting for Dispatcher hierararchy

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
Frediano Ziglio 2020-03-09 02:25:03 +00:00 committed by Frediano Ziglio
parent 724f23e4bd
commit 2b9e1dcd55
5 changed files with 18 additions and 28 deletions

View File

@ -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<DispatcherPrivate> priv;
};

View File

@ -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> 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;

View File

@ -42,8 +42,9 @@
#define MAX_MONITORS_COUNT 16
struct QXLState {
SPICE_CXX_GLIB_ALLOCATOR
QXLInstance *qxl;
Dispatcher *dispatcher;
red::shared_ptr<Dispatcher> 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<Dispatcher>(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)

View File

@ -135,7 +135,7 @@ struct RedsState {
SpiceCoreInterfaceInternal core;
red::safe_list<QXLInstance*> qxl_instances; // XXX owning
MainDispatcher *main_dispatcher;
red::shared_ptr<MainDispatcher> main_dispatcher;
RedRecord *record;
};

View File

@ -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<MainDispatcher>(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)