[vlc-commits] events: use flat table of events

Rémi Denis-Courmont git at videolan.org
Mon May 15 23:35:04 CEST 2017


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue May 16 00:26:20 2017 +0300| [48ad0bf93bf60cb2cf503e737da623ffce4550fa] | committer: Rémi Denis-Courmont

events: use flat table of events

This avoids iterating through the table of events everytime an
event is sent.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=48ad0bf93bf60cb2cf503e737da623ffce4550fa
---

 include/vlc_events.h |  32 +++++++----
 src/misc/events.c    | 153 ++++++++++++++++++---------------------------------
 2 files changed, 74 insertions(+), 111 deletions(-)

diff --git a/include/vlc_events.h b/include/vlc_events.h
index 2dd154c1d1..a0fafb6abb 100644
--- a/include/vlc_events.h
+++ b/include/vlc_events.h
@@ -96,18 +96,6 @@
  * Event Type
  *****************************************************************************/
 
-/* Private structure defined in misc/events.c */
-struct vlc_event_listeners_group_t;
-
-/* Event manager type */
-typedef struct vlc_event_manager_t
-{
-    void * p_obj;
-    vlc_mutex_t object_lock;
-    vlc_mutex_t event_sending_lock;
-    DECL_ARRAY(struct vlc_event_listeners_group_t *) listeners_groups;
-} vlc_event_manager_t;
-
 /* List of event */
 typedef enum vlc_event_type_t {
     /* Input item events */
@@ -122,6 +110,26 @@ typedef enum vlc_event_type_t {
     vlc_InputItemPreparseEnded,
 } vlc_event_type_t;
 
+typedef struct vlc_event_listeners_group_t
+{
+    DECL_ARRAY(struct vlc_event_listener_t *) listeners;
+
+   /* Used in vlc_event_send() to make sure to behave
+      Correctly when vlc_event_detach was called during
+      a callback */
+    bool          b_sublistener_removed;
+
+} vlc_event_listeners_group_t;
+
+/* Event manager type */
+typedef struct vlc_event_manager_t
+{
+    void * p_obj;
+    vlc_mutex_t object_lock;
+    vlc_mutex_t event_sending_lock;
+    vlc_event_listeners_group_t events[vlc_InputItemPreparseEnded + 1];
+} vlc_event_manager_t;
+
 /* Event definition */
 typedef struct vlc_event_t
 {
diff --git a/src/misc/events.c b/src/misc/events.c
index 9c0d5807bc..d909f4dff8 100644
--- a/src/misc/events.c
+++ b/src/misc/events.c
@@ -52,18 +52,6 @@ typedef struct vlc_event_listener_t
     vlc_event_callback_t pf_callback;
 } vlc_event_listener_t;
 
-typedef struct vlc_event_listeners_group_t
-{
-    vlc_event_type_t    event_type;
-    DECL_ARRAY(struct vlc_event_listener_t *) listeners;
-
-   /* Used in vlc_event_send() to make sure to behave
-      Correctly when vlc_event_detach was called during
-      a callback */
-    bool          b_sublistener_removed;
-
-} vlc_event_listeners_group_t;
-
 static bool
 listeners_are_equal( vlc_event_listener_t * listener1,
                      vlc_event_listener_t * listener2 )
@@ -107,7 +95,10 @@ int vlc_event_manager_init( vlc_event_manager_t * p_em, void * p_obj )
      * will never gets triggered.
      * */
     vlc_mutex_init_recursive( &p_em->event_sending_lock );
-    ARRAY_INIT( p_em->listeners_groups );
+
+    for( size_t i = 0; i < ARRAY_SIZE(p_em->events); i++ )
+       ARRAY_INIT( p_em->events[i].listeners );
+
     return VLC_SUCCESS;
 }
 
@@ -116,20 +107,20 @@ int vlc_event_manager_init( vlc_event_manager_t * p_em, void * p_obj )
  */
 void vlc_event_manager_fini( vlc_event_manager_t * p_em )
 {
-    struct vlc_event_listeners_group_t * listeners_group;
     struct vlc_event_listener_t * listener;
 
     vlc_mutex_destroy( &p_em->object_lock );
     vlc_mutex_destroy( &p_em->event_sending_lock );
 
-    FOREACH_ARRAY( listeners_group, p_em->listeners_groups )
-        FOREACH_ARRAY( listener, listeners_group->listeners )
+    for( size_t i = 0; i < ARRAY_SIZE(p_em->events); i++ )
+    {
+        struct vlc_event_listeners_group_t *slot = p_em->events + i;
+
+        FOREACH_ARRAY( listener, slot->listeners )
             free( listener );
         FOREACH_END()
-        ARRAY_RESET( listeners_group->listeners );
-        free( listeners_group );
-    FOREACH_END()
-    ARRAY_RESET( p_em->listeners_groups );
+        ARRAY_RESET( slot->listeners );
+    }
 }
 
 /**
@@ -139,19 +130,7 @@ int vlc_event_manager_register_event_type(
         vlc_event_manager_t * p_em,
         vlc_event_type_t event_type )
 {
-    vlc_event_listeners_group_t * listeners_group;
-    listeners_group = malloc(sizeof(vlc_event_listeners_group_t));
-
-    if( !listeners_group )
-        return VLC_ENOMEM;
-
-    listeners_group->event_type = event_type;
-    ARRAY_INIT( listeners_group->listeners );
-
-    vlc_mutex_lock( &p_em->object_lock );
-    ARRAY_APPEND( p_em->listeners_groups, listeners_group );
-    vlc_mutex_unlock( &p_em->object_lock );
-
+    (void) p_em; (void) event_type;
     return VLC_SUCCESS;
 }
 
@@ -161,10 +140,11 @@ int vlc_event_manager_register_event_type(
 void vlc_event_send( vlc_event_manager_t * p_em,
                      vlc_event_t * p_event )
 {
-    vlc_event_listeners_group_t * listeners_group = NULL;
+    vlc_event_listeners_group_t *slot = &p_em->events[p_event->type];
     vlc_event_listener_t * listener;
     vlc_event_listener_t * array_of_cached_listeners = NULL;
     vlc_event_listener_t * cached_listener;
+
     int i, i_cached_listeners = 0;
 
     /* Fill event with the sending object now */
@@ -173,60 +153,45 @@ void vlc_event_send( vlc_event_manager_t * p_em,
     vlc_mutex_lock( &p_em->event_sending_lock ) ;
     vlc_mutex_lock( &p_em->object_lock );
 
-    FOREACH_ARRAY( listeners_group, p_em->listeners_groups )
-        if( listeners_group->event_type == p_event->type )
-        {
-            if( listeners_group->listeners.i_size <= 0 )
-                break;
+    if( slot->listeners.i_size <= 0 )
+    {
+        vlc_mutex_unlock( &p_em->object_lock );
+        vlc_mutex_unlock( &p_em->event_sending_lock ) ;
+        return;
+    }
 
-            /* Save the function to call */
-            i_cached_listeners = listeners_group->listeners.i_size;
-            array_of_cached_listeners = malloc(
+    /* Save the function to call */
+    i_cached_listeners = slot->listeners.i_size;
+    array_of_cached_listeners = malloc(
                     sizeof(vlc_event_listener_t)*i_cached_listeners );
-            if( !array_of_cached_listeners )
-            {
-                vlc_mutex_unlock( &p_em->object_lock );
-                vlc_mutex_unlock( &p_em->event_sending_lock ) ;
-                return;
-            }
-
-            cached_listener = array_of_cached_listeners;
-            FOREACH_ARRAY( listener, listeners_group->listeners )
-                memcpy( cached_listener, listener, sizeof(vlc_event_listener_t));
-                cached_listener++;
-            FOREACH_END()
+    if( unlikely(!array_of_cached_listeners) )
+        abort();
 
-            break;
-        }
+    cached_listener = array_of_cached_listeners;
+    FOREACH_ARRAY( listener, slot->listeners )
+        memcpy( cached_listener, listener, sizeof(vlc_event_listener_t) );
+        cached_listener++;
     FOREACH_END()
 
     /* Track item removed from *this* thread, with a simple flag. Indeed
      * event_sending_lock is a recursive lock. This has the advantage of
      * allowing to remove an event listener from within a callback */
-    listeners_group->b_sublistener_removed = false;
+    slot->b_sublistener_removed = false;
 
     vlc_mutex_unlock( &p_em->object_lock );
 
     /* Call the function attached */
     cached_listener = array_of_cached_listeners;
 
-    if( !listeners_group || !array_of_cached_listeners )
-    {
-        free( array_of_cached_listeners );
-        vlc_mutex_unlock( &p_em->event_sending_lock );
-        return;
-    }
-
-
     for( i = 0; i < i_cached_listeners; i++ )
     {
-        if( listeners_group->b_sublistener_removed )
+        if( slot->b_sublistener_removed )
         {
             /* If a callback was removed inside one of our callback, this gets
              * called */
             bool valid_listener;
             vlc_mutex_lock( &p_em->object_lock );
-            valid_listener = group_contains_listener( listeners_group, cached_listener );
+            valid_listener = group_contains_listener( slot, cached_listener );
             vlc_mutex_unlock( &p_em->object_lock );
             if( !valid_listener )
             {
@@ -251,8 +216,9 @@ int vlc_event_attach( vlc_event_manager_t * p_em,
                       vlc_event_callback_t pf_callback,
                       void *p_user_data )
 {
-    vlc_event_listeners_group_t * listeners_group;
     vlc_event_listener_t * listener;
+    vlc_event_listeners_group_t *slot = &p_em->events[event_type];
+
     listener = malloc(sizeof(vlc_event_listener_t));
     if( !listener )
         return VLC_ENOMEM;
@@ -261,16 +227,9 @@ int vlc_event_attach( vlc_event_manager_t * p_em,
     listener->pf_callback = pf_callback;
 
     vlc_mutex_lock( &p_em->object_lock );
-    FOREACH_ARRAY( listeners_group, p_em->listeners_groups )
-        if( listeners_group->event_type == event_type )
-        {
-            ARRAY_APPEND( listeners_group->listeners, listener );
-            vlc_mutex_unlock( &p_em->object_lock );
-            return VLC_SUCCESS;
-        }
-    FOREACH_END()
-    /* Unknown event = BUG */
-    vlc_assert_unreachable();
+    ARRAY_APPEND( slot->listeners, listener );
+    vlc_mutex_unlock( &p_em->object_lock );
+    return VLC_SUCCESS;
 }
 
 /**
@@ -282,32 +241,28 @@ void vlc_event_detach( vlc_event_manager_t *p_em,
                        vlc_event_callback_t pf_callback,
                        void *p_user_data )
 {
-    vlc_event_listeners_group_t * listeners_group;
+    vlc_event_listeners_group_t *slot = &p_em->events[event_type];
     struct vlc_event_listener_t * listener;
 
     vlc_mutex_lock( &p_em->event_sending_lock );
     vlc_mutex_lock( &p_em->object_lock );
-    FOREACH_ARRAY( listeners_group, p_em->listeners_groups )
-        if( listeners_group->event_type == event_type )
+
+    FOREACH_ARRAY( listener, slot->listeners )
+        if( listener->pf_callback == pf_callback &&
+            listener->p_user_data == p_user_data )
         {
-            FOREACH_ARRAY( listener, listeners_group->listeners )
-                if( listener->pf_callback == pf_callback &&
-                    listener->p_user_data == p_user_data )
-                {
-                    /* Tell vlc_event_send, we did remove an item from that group,
-                       in case vlc_event_send is in our caller stack  */
-                    listeners_group->b_sublistener_removed = true;
-
-                    /* that's our listener */
-                    ARRAY_REMOVE( listeners_group->listeners,
-                        fe_idx /* This comes from the macro (and that's why
-                                  I hate macro) */ );
-                    free( listener );
-                    vlc_mutex_unlock( &p_em->event_sending_lock );
-                    vlc_mutex_unlock( &p_em->object_lock );
-                    return;
-                }
-            FOREACH_END()
+            /* Tell vlc_event_send, we did remove an item from that group,
+               in case vlc_event_send is in our caller stack  */
+            slot->b_sublistener_removed = true;
+
+            /* that's our listener */
+            ARRAY_REMOVE( slot->listeners,
+                          fe_idx /* This comes from the macro (and that's why
+                                    I hate macro) */ );
+            free( listener );
+            vlc_mutex_unlock( &p_em->event_sending_lock );
+            vlc_mutex_unlock( &p_em->object_lock );
+            return;
         }
     FOREACH_END()
 



More information about the vlc-commits mailing list