From 96d708c2768aa9ee43b4d48957f8f85c68f016de Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 14 Oct 2008 23:35:20 +0300 Subject: [PATCH] Count message references and get rid of the global message ring buffer Each susbcriber has its own ring buffer already. --- include/vlc_messages.h | 12 +++ src/libvlc.c | 6 -- src/libvlc.h | 7 -- src/misc/messages.c | 184 ++++++++++------------------------------- 4 files changed, 54 insertions(+), 155 deletions(-) diff --git a/include/vlc_messages.h b/include/vlc_messages.h index 4d0d5072a7..bf8d2ddf4d 100644 --- a/include/vlc_messages.h +++ b/include/vlc_messages.h @@ -55,6 +55,7 @@ typedef struct char * psz_header; /**< Additional header */ mtime_t date; /**< Message date */ + gc_object_t vlc_gc_data; } msg_item_t; /* Message types */ @@ -67,6 +68,17 @@ typedef struct /** debug messages */ #define VLC_MSG_DBG 3 +static inline msg_item_t *msg_Hold (msg_item_t *msg) +{ + vlc_hold (&msg->vlc_gc_data); + return msg; +} + +static inline void msg_Release (msg_item_t *msg) +{ + vlc_release (&msg->vlc_gc_data); +} + /** * Used by interface plugins which subscribe to the message bank. */ diff --git a/src/libvlc.c b/src/libvlc.c index f300daa0e6..d6e6be4efc 100644 --- a/src/libvlc.c +++ b/src/libvlc.c @@ -744,11 +744,6 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc, if( priv->b_color ) priv->b_color = config_GetInt( p_libvlc, "color" ) > 0; - /* - * Output messages that may still be in the queue - */ - msg_Flush( p_libvlc ); - if( !config_GetInt( p_libvlc, "fpu" ) ) cpu_flags &= ~CPU_CAPABILITY_FPU; @@ -1142,7 +1137,6 @@ int libvlc_InternalDestroy( libvlc_int_t *p_libvlc ) } vlc_mutex_unlock( &global_lock ); - msg_Flush( p_libvlc ); msg_Destroy( p_libvlc ); /* Destroy mutexes */ diff --git a/src/libvlc.h b/src/libvlc.h index ddeda34993..5859ece03b 100644 --- a/src/libvlc.h +++ b/src/libvlc.h @@ -79,12 +79,6 @@ typedef struct msg_bank_t vlc_mutex_t lock; vlc_cond_t wait; - /* Message queue */ - msg_item_t msg[VLC_MSG_QSIZE]; /**< message queue */ - int i_start; - int i_stop; - bool b_overflow; - /* Subscribers */ int i_sub; msg_subscription_t **pp_sub; @@ -96,7 +90,6 @@ typedef struct msg_bank_t } msg_bank_t; void msg_Create (libvlc_int_t *); -void msg_Flush (libvlc_int_t *); void msg_Destroy (libvlc_int_t *); /** Internal message stack context */ diff --git a/src/misc/messages.c b/src/misc/messages.c index 81c8aba855..69ba87667d 100644 --- a/src/misc/messages.c +++ b/src/misc/messages.c @@ -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 ***************************************************************************** -- 2.39.2