]> git.sesse.net Git - vlc/blobdiff - src/misc/messages.c
Count message references and get rid of the global message ring buffer
[vlc] / src / misc / messages.c
index 81c8aba855e984e124723f7a5e77267ba3c9dee3..69ba87667d949ee814614a0c064b54b8114e1eed 100644 (file)
@@ -86,7 +86,6 @@ static inline msg_bank_t *libvlc_bank (libvlc_int_t *inst)
  *****************************************************************************/
 static void QueueMsg ( vlc_object_t *, int, const char *,
                        const char *, va_list );
-static void FlushMsg ( msg_bank_t * );
 static void PrintMsg ( vlc_object_t *, msg_item_t * );
 
 static vlc_mutex_t msg_stack_lock = VLC_STATIC_MUTEX;
@@ -105,11 +104,8 @@ void msg_Create (libvlc_int_t *p_libvlc)
     vlc_dictionary_init( &priv->msg_enabled_objects, 0 );
     priv->msg_all_objects_enabled = true;
 
-    QUEUE.b_overflow = false;
-    QUEUE.i_start = 0;
-    QUEUE.i_stop = 0;
     QUEUE.i_sub = 0;
-    QUEUE.pp_sub = 0;
+    QUEUE.pp_sub = NULL;
 
 #ifdef UNDER_CE
     QUEUE.logfile =
@@ -125,18 +121,6 @@ void msg_Create (libvlc_int_t *p_libvlc)
     vlc_mutex_unlock( &msg_stack_lock );
 }
 
-/**
- * Flush all message queues
- */
-void msg_Flush (libvlc_int_t *p_libvlc)
-{
-    libvlc_priv_t *priv = libvlc_priv (p_libvlc);
-    vlc_mutex_lock( &QUEUE.lock );
-    FlushMsg( &QUEUE );
-    vlc_mutex_unlock( &QUEUE.lock );
-}
-
-
 /**
  * Object Printing selection
  */
@@ -180,8 +164,6 @@ void msg_Destroy (libvlc_int_t *p_libvlc)
     if( QUEUE.i_sub )
         msg_Err( p_libvlc, "stale interface subscribers (VLC might crash)" );
 
-    FlushMsg( &QUEUE );
-
     vlc_mutex_lock( &msg_stack_lock );
     if( --banks == 0 )
         vlc_threadvar_delete( &msg_context );
@@ -213,10 +195,7 @@ static void *msg_thread (void *data)
     msg_subscription_t *sub = data;
     msg_bank_t *bank = libvlc_bank (sub->instance);
 
-    /* TODO: finer-grained locking and/or msg_item_t refcount */
     vlc_mutex_lock (&bank->lock);
-    mutex_cleanup_push (&bank->lock);
-
     for (;;)
     {
         /* Wait for messages */
@@ -224,15 +203,24 @@ static void *msg_thread (void *data)
         assert (sub->end < VLC_MSG_QSIZE);
         while (sub->begin != sub->end)
         {
-            sub->func (sub->opaque, sub->items[sub->begin], sub->overruns);
+            msg_item_t *msg = sub->items[sub->begin];
+            unsigned overruns = sub->overruns;
+
             if (++sub->begin == VLC_MSG_QSIZE)
                 sub->begin = 0;
             sub->overruns = 0;
+            vlc_mutex_unlock (&bank->lock);
+
+            sub->func (sub->opaque, msg, overruns);
+            msg_Release (msg);
+
+            vlc_mutex_lock (&bank->lock);
         }
+
+        mutex_cleanup_push (&bank->lock);
         vlc_cond_wait (&bank->wait, &bank->lock);
+        vlc_cleanup_pop ();
     }
-
-    vlc_cleanup_pop ();
     assert (0);
 }
 
@@ -311,6 +299,19 @@ void __msg_GenericVa( vlc_object_t *p_this, int i_type, const char *psz_module,
     QueueMsg( p_this, i_type, psz_module, psz_format, args );
 }
 
+/**
+ * Destroys a message.
+ */
+static void msg_Free (gc_object_t *gc)
+{
+    msg_item_t *msg = vlc_priv (gc, msg_item_t);
+
+    free (msg->psz_module);
+    free (msg->psz_msg);
+    free (msg->psz_header);
+    free (msg);
+}
+
 /**
  * Add a message to a queue
  *
@@ -329,9 +330,12 @@ static void QueueMsg( vlc_object_t *p_this, int i_type, const char *psz_module,
     char *       psz_str = NULL;                 /* formatted message string */
     char *       psz_header = NULL;
     va_list      args;
-    msg_item_t * p_item = NULL;                        /* pointer to message */
-    msg_item_t   item;                    /* message in case of a full queue */
-    msg_bank_t  *p_queue;
+    msg_item_t * p_item = malloc (sizeof (*p_item));
+
+    if (p_item == NULL)
+        return; /* Uho! */
+
+    vlc_gc_init (p_item, msg_Free);
 
 #if !defined(HAVE_VASPRINTF) || defined(__APPLE__) || defined(SYS_BEOS)
     int          i_size = strlen(psz_format) + INTF_MAX_MSG_SIZE;
@@ -466,57 +470,9 @@ static void QueueMsg( vlc_object_t *p_this, int i_type, const char *psz_module,
     psz_str[ i_size - 1 ] = 0; /* Just in case */
 #endif
 
-    p_queue = &QUEUE;
+    msg_bank_t *p_queue = &QUEUE;
     vlc_mutex_lock( &p_queue->lock );
 
-    /* Check there is room in the queue for our message */
-    if( p_queue->b_overflow )
-    {
-        FlushMsg( p_queue );
-
-        if( ((p_queue->i_stop - p_queue->i_start + 1) % VLC_MSG_QSIZE) == 0 )
-        {
-            /* Still in overflow mode, print from a dummy item */
-            p_item = &item;
-        }
-        else
-        {
-            /* Pheeew, at last, there is room in the queue! */
-            p_queue->b_overflow = false;
-        }
-    }
-    else if( ((p_queue->i_stop - p_queue->i_start + 2) % VLC_MSG_QSIZE) == 0 )
-    {
-        FlushMsg( p_queue );
-
-        if( ((p_queue->i_stop - p_queue->i_start + 2) % VLC_MSG_QSIZE) == 0 )
-        {
-            p_queue->b_overflow = true;
-
-            /* Put the overflow message in the queue */
-            p_item = p_queue->msg + p_queue->i_stop;
-            p_queue->i_stop = (p_queue->i_stop + 1) % VLC_MSG_QSIZE;
-
-            p_item->i_type =        VLC_MSG_WARN;
-            p_item->i_object_id =   (uintptr_t)p_this;
-            p_item->psz_object_type = p_this->psz_object_type;
-            p_item->psz_module =    strdup( "message" );
-            p_item->psz_msg =       strdup( "message queue overflowed" );
-            p_item->psz_header =    NULL;
-
-            PrintMsg( p_this, p_item );
-            /* We print from a dummy item */
-            p_item = &item;
-        }
-    }
-
-    if( !p_queue->b_overflow )
-    {
-        /* Put the message in the queue */
-        p_item = p_queue->msg + p_queue->i_stop;
-        p_queue->i_stop = (p_queue->i_stop + 1) % VLC_MSG_QSIZE;
-    }
-
     /* Fill message information fields */
     p_item->i_type =        i_type;
     p_item->i_object_id =   (uintptr_t)p_this;
@@ -527,78 +483,22 @@ static void QueueMsg( vlc_object_t *p_this, int i_type, const char *psz_module,
 
     PrintMsg( p_this, p_item );
 #define bank p_queue
-    if( p_item == &item )
+    for (int i = 0; i < bank->i_sub; i++)
     {
-        free( p_item->psz_module );
-        free( p_item->psz_msg );
-        free( p_item->psz_header );
-        for (int i = 0; i < bank->i_sub; i++)
-            bank->pp_sub[i]->overruns++;
-    }
-    else
-    {
-        for (int i = 0; i < bank->i_sub; i++)
+        msg_subscription_t *sub = bank->pp_sub[i];
+        if ((sub->end + 1 - sub->begin) % VLC_MSG_QSIZE)
         {
-            msg_subscription_t *sub = bank->pp_sub[i];
-            if ((sub->end + 1 - sub->begin) % VLC_MSG_QSIZE)
-            {
-                sub->items[sub->end++] = p_item;
-                if (sub->end == VLC_MSG_QSIZE)
-                    sub->end = 0;
-            }
-            else
-                sub->overruns++;
+            sub->items[sub->end++] = msg_Hold (p_item);
+            if (sub->end == VLC_MSG_QSIZE)
+                sub->end = 0;
         }
-        vlc_cond_broadcast (&bank->wait);
+        else
+            sub->overruns++;
     }
+    vlc_cond_broadcast (&bank->wait);
     vlc_mutex_unlock (&bank->lock);
 }
 
-/* following functions are local */
-
-/*****************************************************************************
- * FlushMsg
- *****************************************************************************
- * Print all messages remaining in queue. MESSAGE QUEUE MUST BE LOCKED, since
- * this function does not check the lock.
- *****************************************************************************/
-static void FlushMsg ( msg_bank_t *p_queue )
-{
-    int i_index, i_start, i_stop;
-
-    /* Get the maximum message index that can be freed */
-    i_stop = p_queue->i_stop;
-
-    /* Check until which value we can free messages */
-    for( i_index = 0; i_index < p_queue->i_sub; i_index++ )
-    {
-        i_start = p_queue->pp_sub[ i_index ]->begin;
-
-        /* If this subscriber is late, we don't free messages before
-         * his i_start value, otherwise he'll miss messages */
-        if(   ( i_start < i_stop
-               && (p_queue->i_stop <= i_start || i_stop <= p_queue->i_stop) )
-           || ( i_stop < i_start
-               && (i_stop <= p_queue->i_stop && p_queue->i_stop <= i_start) ) )
-        {
-            i_stop = i_start;
-        }
-    }
-
-    /* Free message data */
-    for( i_index = p_queue->i_start;
-         i_index != i_stop;
-         i_index = (i_index+1) % VLC_MSG_QSIZE )
-    {
-        free( p_queue->msg[i_index].psz_msg );
-        free( p_queue->msg[i_index].psz_module );
-        free( p_queue->msg[i_index].psz_header );
-    }
-
-    /* Update the new start value */
-    p_queue->i_start = i_index;
-}
-
 /*****************************************************************************
  * PrintMsg: output a standard message item to stderr
  *****************************************************************************