]> git.sesse.net Git - vlc/commitdiff
block_FifoWake: force the block_FifoGet()'ing thread to wakeup without
authorRémi Denis-Courmont <rem@videolan.org>
Sun, 16 Sep 2007 12:27:40 +0000 (12:27 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Sun, 16 Sep 2007 12:27:40 +0000 (12:27 +0000)
queuing any data - this is mostly useful when quitting

include/vlc_block.h
src/misc/block.c

index 8c09f9436eff68d645d551e1d2e2caaed3a0febd..00687afe40d1f624bc2a3691adb74735b88f9329 100644 (file)
@@ -262,6 +262,8 @@ static inline block_t *block_ChainGather( block_t *p_list )
  *      only one getting data from the fifo.
  * - block_FifoCount : how many packets are waiting in the fifo
  * - block_FifoSize : how many cumulated bytes are waiting in the fifo
+ * - block_FifoWake : wake ups a thread with block_FifoGet() = NULL
+ *   (this is used to wakeup a thread when there is no data to queue)
  ****************************************************************************/
 
 #define block_FifoNew( a ) __block_FifoNew( VLC_OBJECT(a) )
@@ -269,6 +271,7 @@ VLC_EXPORT( block_fifo_t *, __block_FifoNew,    ( vlc_object_t * ) );
 VLC_EXPORT( void,           block_FifoRelease,  ( block_fifo_t * ) );
 VLC_EXPORT( void,           block_FifoEmpty,    ( block_fifo_t * ) );
 VLC_EXPORT( int,            block_FifoPut,      ( block_fifo_t *, block_t * ) );
+VLC_EXPORT( void,           block_FifoWake,     ( block_fifo_t * ) );
 VLC_EXPORT( block_t *,      block_FifoGet,      ( block_fifo_t * ) );
 VLC_EXPORT( block_t *,      block_FifoShow,     ( block_fifo_t * ) );
 VLC_EXPORT( size_t,         block_FifoSize,     ( const block_fifo_t *p_fifo ) );
index cbfd5e9cb7cae069d030a2d7fa51fac09ba6ed72..12fa0465053ad414234206a8c6cb1802e439a749 100644 (file)
@@ -160,10 +160,11 @@ struct block_fifo_t
     vlc_mutex_t         lock;                         /* fifo data lock */
     vlc_cond_t          wait;         /* fifo data conditional variable */
 
-    size_t              i_depth;
     block_t             *p_first;
     block_t             **pp_last;
+    size_t              i_depth;
     size_t              i_size;
+    vlc_bool_t          b_force_wake;
 };
 
 block_fifo_t *__block_FifoNew( vlc_object_t *p_obj )
@@ -173,9 +174,10 @@ block_fifo_t *__block_FifoNew( vlc_object_t *p_obj )
     p_fifo = malloc( sizeof( block_fifo_t ) );
     vlc_mutex_init( p_obj, &p_fifo->lock );
     vlc_cond_init( p_obj, &p_fifo->wait );
-    p_fifo->i_depth = p_fifo->i_size = 0;
     p_fifo->p_first = NULL;
     p_fifo->pp_last = &p_fifo->p_first;
+    p_fifo->i_depth = p_fifo->i_size = 0;
+    p_fifo->b_force_wake = VLC_FALSE;
 
     return p_fifo;
 }
@@ -233,22 +235,38 @@ int block_FifoPut( block_fifo_t *p_fifo, block_t *p_block )
     return i_size;
 }
 
+void block_FifoWake( block_fifo_t *p_fifo )
+{
+    vlc_mutex_lock( &p_fifo->lock );
+    if( p_fifo->p_first == NULL )
+        p_fifo->b_force_wake = VLC_TRUE;
+    vlc_cond_signal( &p_fifo->wait );
+    vlc_mutex_unlock( &p_fifo->lock );
+}
+
 block_t *block_FifoGet( block_fifo_t *p_fifo )
 {
     block_t *b;
 
     vlc_mutex_lock( &p_fifo->lock );
 
-    /* We do a while here because there is a race condition in the
-     * win32 implementation of vlc_cond_wait() (We can't be sure the fifo
-     * hasn't been emptied again since we were signaled). */
-    while( p_fifo->p_first == NULL )
+    /* Remember vlc_cond_wait() may cause spurious wakeups
+     * (on both Win32 and POSIX) */
+    while( ( p_fifo->p_first == NULL ) && !p_fifo->b_force_wake )
     {
         vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
     }
 
     b = p_fifo->p_first;
 
+    p_fifo->b_force_wake = VLC_FALSE;
+    if( b == NULL )
+    {
+        /* Forced wakeup */
+        vlc_mutex_unlock( &p_fifo->lock );
+        return NULL;
+    }
+
     p_fifo->p_first = b->p_next;
     p_fifo->i_depth--;
     p_fifo->i_size -= b->i_buffer;