[mutter/wip/carlosg/input-thread: 57/87] backends/native: Protect MetaBarrierManagerNative




commit e76a7f43e02d360b624425816181a28144b61faf
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Aug 11 20:21:08 2020 +0200

    backends/native: Protect MetaBarrierManagerNative
    
    While barriers will be added from the main thread, the native barrier
    manager will sit close to the MetaSeatImpl in its own thread. Add the
    necessary locking so that we can pass MetaBarrierImplNative from the
    UI thread to the input thread, and ensure the MetaBarrier signals are
    still emitted in the UI thread.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403>

 src/backends/native/meta-barrier-native.c | 64 +++++++++++++++++++++++++++----
 1 file changed, 57 insertions(+), 7 deletions(-)
---
diff --git a/src/backends/native/meta-barrier-native.c b/src/backends/native/meta-barrier-native.c
index bdb006fb13..8db73ee068 100644
--- a/src/backends/native/meta-barrier-native.c
+++ b/src/backends/native/meta-barrier-native.c
@@ -43,6 +43,7 @@
 struct _MetaBarrierManagerNative
 {
   GHashTable *barriers;
+  GMutex mutex;
 };
 
 typedef enum
@@ -77,6 +78,7 @@ struct _MetaBarrierImplNative
   int                       trigger_serial;
   guint32                   last_event_time;
   MetaBarrierDirection      blocked_dir;
+  GMainContext             *main_context;
 };
 
 G_DEFINE_TYPE (MetaBarrierImplNative,
@@ -340,6 +342,49 @@ typedef struct _MetaBarrierEventData
   float               dy;
 } MetaBarrierEventData;
 
+typedef struct
+{
+  MetaBarrierEvent *event;
+  MetaBarrier *barrier;
+  MetaBarrierState state;
+} MetaBarrierIdleData;
+
+static gboolean
+emit_event_idle (MetaBarrierIdleData *idle_data)
+{
+  if (idle_data->state == META_BARRIER_STATE_HELD)
+    _meta_barrier_emit_hit_signal (idle_data->barrier, idle_data->event);
+  else
+    _meta_barrier_emit_left_signal (idle_data->barrier, idle_data->event);
+
+  meta_barrier_event_unref (idle_data->event);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+queue_event (MetaBarrierImplNative *self,
+             MetaBarrierEvent      *event)
+{
+  MetaBarrierIdleData *idle_data;
+  GSource *source;
+
+  idle_data = g_new0 (MetaBarrierIdleData, 1);
+  idle_data->state = self->state;
+  idle_data->barrier = self->barrier;
+  idle_data->event = event;
+
+  source = g_idle_source_new ();
+  g_source_set_priority (source, G_PRIORITY_HIGH);
+  g_source_set_callback (source,
+                         (GSourceFunc) emit_event_idle,
+                         idle_data,
+                         g_free);
+
+  g_source_attach (source, self->main_context);
+  g_source_unref (source);
+}
+
 static void
 emit_barrier_event (MetaBarrierImplNative *self,
                     guint32                time,
@@ -350,7 +395,6 @@ emit_barrier_event (MetaBarrierImplNative *self,
                     float                  dx,
                     float                  dy)
 {
-  MetaBarrier *barrier = self->barrier;
   MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
   MetaBarrierState old_state = self->state;
 
@@ -389,12 +433,7 @@ emit_barrier_event (MetaBarrierImplNative *self,
 
   self->last_event_time = time;
 
-  if (self->state == META_BARRIER_STATE_HELD)
-    _meta_barrier_emit_hit_signal (barrier, event);
-  else
-    _meta_barrier_emit_left_signal (barrier, event);
-
-  meta_barrier_event_unref (event);
+  queue_event (self, event);
 }
 
 static void
@@ -479,6 +518,8 @@ meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
   if (!clutter_input_device_get_coords (device, NULL, &prev_pos))
     return;
 
+  g_mutex_lock (&manager->mutex);
+
   prev_x = prev_pos.x;
   prev_y = prev_pos.y;
 
@@ -523,6 +564,8 @@ meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
   g_hash_table_foreach (manager->barriers,
                         maybe_emit_barrier_event,
                         &barrier_event_data);
+
+  g_mutex_unlock (&manager->mutex);
 }
 
 static gboolean
@@ -549,7 +592,10 @@ _meta_barrier_impl_native_destroy (MetaBarrierImpl *impl)
 {
   MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
 
+  g_mutex_lock (&self->manager->mutex);
   g_hash_table_remove (self->manager->barriers, self);
+  g_mutex_unlock (&self->manager->mutex);
+  g_main_context_unref (self->main_context);
   self->is_active = FALSE;
 }
 
@@ -565,10 +611,13 @@ meta_barrier_impl_native_new (MetaBarrier *barrier)
 
   self->barrier = barrier;
   self->is_active = TRUE;
+  self->main_context = g_main_context_ref_thread_default ();
 
   manager = meta_seat_native_get_barrier_manager (META_SEAT_NATIVE (seat));
   self->manager = manager;
+  g_mutex_lock (&manager->mutex);
   g_hash_table_add (manager->barriers, self);
+  g_mutex_unlock (&manager->mutex);
 
   return META_BARRIER_IMPL (self);
 }
@@ -596,6 +645,7 @@ meta_barrier_manager_native_new (void)
   manager = g_new0 (MetaBarrierManagerNative, 1);
 
   manager->barriers = g_hash_table_new (NULL, NULL);
+  g_mutex_init (&manager->mutex);
 
   return manager;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]