Commit 96d708c2 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Count message references and get rid of the global message ring buffer

Each susbcriber has its own ring buffer already.
parent 0756eece
......@@ -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.
*/
......
......@@ -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 */
......
......@@ -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 */
......
......@@ -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
*****************************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment