[vlc-devel] [PATCH 4/4] fifo: use the queue API

RĂ©mi Denis-Courmont remi at remlab.net
Sat Apr 11 20:41:06 CEST 2020


---
 include/vlc_block.h | 45 ++++++++++++++-------
 src/misc/fifo.c     | 95 +++++++++++----------------------------------
 2 files changed, 54 insertions(+), 86 deletions(-)

diff --git a/include/vlc_block.h b/include/vlc_block.h
index 2c98499db0..b57b4698cb 100644
--- a/include/vlc_block.h
+++ b/include/vlc_block.h
@@ -438,6 +438,8 @@ static inline block_t *block_ChainGather( block_t *p_list )
  * @{
  */
 
+#include <vlc_queue.h>
+
 /**
  * Creates a thread-safe FIFO queue of blocks.
  *
@@ -480,6 +482,11 @@ VLC_API block_t *block_FifoShow(block_fifo_t *);
 
 typedef struct block_fifo_t vlc_fifo_t;
 
+static inline vlc_queue_t *vlc_fifo_queue(const vlc_fifo_t *fifo)
+{
+    return (vlc_queue_t *)fifo;
+}
+
 /**
  * Locks a block FIFO.
  *
@@ -493,7 +500,10 @@ typedef struct block_fifo_t vlc_fifo_t;
  * @warning Recursively locking a single FIFO is undefined. Locking more than
  * one FIFO at a time may lead to lock inversion; mind the locking order.
  */
-VLC_API void vlc_fifo_Lock(vlc_fifo_t *);
+static inline void vlc_fifo_Lock(vlc_fifo_t *fifo)
+{
+    vlc_queue_Lock(vlc_fifo_queue(fifo));
+}
 
 /**
  * Unlocks a block FIFO.
@@ -503,7 +513,10 @@ VLC_API void vlc_fifo_Lock(vlc_fifo_t *);
  *
  * @note This function is not a cancellation point.
  */
-VLC_API void vlc_fifo_Unlock(vlc_fifo_t *);
+static inline void vlc_fifo_Unlock(vlc_fifo_t *fifo)
+{
+    vlc_queue_Unlock(vlc_fifo_queue(fifo));
+}
 
 /**
  * Wakes up one thread waiting on the FIFO, if any.
@@ -513,7 +526,10 @@ VLC_API void vlc_fifo_Unlock(vlc_fifo_t *);
  * @warning For race-free operations, the FIFO should be locked by the calling
  * thread. The function can be called on a unlocked FIFO however.
  */
-VLC_API void vlc_fifo_Signal(vlc_fifo_t *);
+static inline void vlc_fifo_Signal(vlc_fifo_t *fifo)
+{
+    vlc_queue_Signal(vlc_fifo_queue(fifo));
+}
 
 /**
  * Waits on the FIFO.
@@ -526,9 +542,17 @@ VLC_API void vlc_fifo_Signal(vlc_fifo_t *);
  * @note This function is a cancellation point. In case of cancellation, the
  * the FIFO will be locked before cancellation cleanup handlers are processed.
  */
-VLC_API void vlc_fifo_Wait(vlc_fifo_t *);
+static inline void vlc_fifo_Wait(vlc_fifo_t *fifo)
+{
+    vlc_queue_Wait(vlc_fifo_queue(fifo));
+}
 
-VLC_API void vlc_fifo_WaitCond(vlc_fifo_t *, vlc_cond_t *);
+static inline void vlc_fifo_WaitCond(vlc_fifo_t *fifo, vlc_cond_t *condvar)
+{
+    vlc_queue_t *q = vlc_fifo_queue(fifo);
+
+    vlc_cond_wait(condvar, &q->lock);
+}
 
 /**
  * Queues a linked-list of blocks into a locked FIFO.
@@ -541,7 +565,7 @@ VLC_API void vlc_fifo_WaitCond(vlc_fifo_t *, vlc_cond_t *);
  * @warning The FIFO must be locked by the calling thread using
  * vlc_fifo_Lock(). Otherwise behaviour is undefined.
  */
-VLC_API void vlc_fifo_QueueUnlocked(vlc_fifo_t *, block_t *);
+VLC_API void vlc_fifo_QueueUnlocked(vlc_fifo_t *fifo, block_t *);
 
 /**
  * Dequeues the first block from a locked FIFO, if any.
@@ -604,7 +628,7 @@ VLC_API size_t vlc_fifo_GetBytes(const vlc_fifo_t *) VLC_USED;
 
 VLC_USED static inline bool vlc_fifo_IsEmpty(const vlc_fifo_t *fifo)
 {
-    return vlc_fifo_GetCount(fifo) == 0;
+    return vlc_queue_IsEmpty(vlc_fifo_queue(fifo));
 }
 
 static inline void vlc_fifo_Cleanup(void *fifo)
@@ -618,12 +642,7 @@ static inline void vlc_fifo_Cleanup(void *fifo)
  */
 static inline void block_FifoEmpty(block_fifo_t *fifo)
 {
-    block_t *block;
-
-    vlc_fifo_Lock(fifo);
-    block = vlc_fifo_DequeueAllUnlocked(fifo);
-    vlc_fifo_Unlock(fifo);
-    block_ChainRelease(block);
+    block_ChainRelease((block_t *)vlc_queue_DequeueAll(vlc_fifo_queue(fifo)));
 }
 
 /**
diff --git a/src/misc/fifo.c b/src/misc/fifo.c
index 522d52d167..e829bfc8c9 100644
--- a/src/misc/fifo.c
+++ b/src/misc/fifo.c
@@ -37,118 +37,67 @@
  */
 struct block_fifo_t
 {
-    vlc_mutex_t         lock;                         /* fifo data lock */
-    vlc_cond_t          wait;      /**< Wait for data */
-
-    block_t             *p_first;
-    block_t             **pp_last;
+    vlc_queue_t         q;
     size_t              i_depth;
     size_t              i_size;
 };
 
-void vlc_fifo_Lock(vlc_fifo_t *fifo)
-{
-    vlc_mutex_lock(&fifo->lock);
-}
-
-void vlc_fifo_Unlock(vlc_fifo_t *fifo)
-{
-    vlc_mutex_unlock(&fifo->lock);
-}
-
-void vlc_fifo_Signal(vlc_fifo_t *fifo)
-{
-    vlc_cond_signal(&fifo->wait);
-}
+static const ptrdiff_t offset = offsetof (block_t, p_next);
 
-void vlc_fifo_Wait(vlc_fifo_t *fifo)
-{
-    vlc_fifo_WaitCond(fifo, &fifo->wait);
-}
-
-void vlc_fifo_WaitCond(vlc_fifo_t *fifo, vlc_cond_t *condvar)
-{
-    vlc_cond_wait(condvar, &fifo->lock);
-}
+static_assert (offsetof (block_fifo_t, q) == 0, "Problems in <vlc_block.h>");
 
 size_t vlc_fifo_GetCount(const vlc_fifo_t *fifo)
 {
-    vlc_mutex_assert(&fifo->lock);
+    vlc_mutex_assert(&fifo->q.lock);
     return fifo->i_depth;
 }
 
 size_t vlc_fifo_GetBytes(const vlc_fifo_t *fifo)
 {
-    vlc_mutex_assert(&fifo->lock);
+    vlc_mutex_assert(&fifo->q.lock);
     return fifo->i_size;
 }
 
 void vlc_fifo_QueueUnlocked(block_fifo_t *fifo, block_t *block)
 {
-    vlc_mutex_assert(&fifo->lock);
-    assert(*(fifo->pp_last) == NULL);
-
-    *(fifo->pp_last) = block;
-
-    while (block != NULL)
-    {
-        fifo->pp_last = &block->p_next;
+    for (block_t *b = block; b != NULL; b = b->p_next) {
         fifo->i_depth++;
         fifo->i_size += block->i_buffer;
-
-        block = block->p_next;
     }
 
-    vlc_fifo_Signal(fifo);
+    vlc_queue_EnqueueUnlocked(&fifo->q, block, offset);
 }
 
 block_t *vlc_fifo_DequeueUnlocked(block_fifo_t *fifo)
 {
-    vlc_mutex_assert(&fifo->lock);
-
-    block_t *block = fifo->p_first;
-
-    if (block == NULL)
-        return NULL; /* Nothing to do */
-
-    fifo->p_first = block->p_next;
-    if (block->p_next == NULL)
-        fifo->pp_last = &fifo->p_first;
-    block->p_next = NULL;
+    block_t *block = vlc_queue_DequeueUnlocked(&fifo->q, offset);
 
-    assert(fifo->i_depth > 0);
-    fifo->i_depth--;
-    assert(fifo->i_size >= block->i_buffer);
-    fifo->i_size -= block->i_buffer;
+    if (block != NULL) {
+        assert(fifo->i_depth > 0);
+        assert(fifo->i_size >= block->i_buffer);
+        fifo->i_depth--;
+        fifo->i_size -= block->i_buffer;
+    }
 
     return block;
 }
 
 block_t *vlc_fifo_DequeueAllUnlocked(block_fifo_t *fifo)
 {
-    vlc_mutex_assert(&fifo->lock);
-
-    block_t *block = fifo->p_first;
-
-    fifo->p_first = NULL;
-    fifo->pp_last = &fifo->p_first;
     fifo->i_depth = 0;
     fifo->i_size = 0;
-
-    return block;
+    return vlc_queue_DequeueAllUnlocked(&fifo->q);
 }
 
 block_fifo_t *block_FifoNew( void )
 {
     block_fifo_t *p_fifo = malloc( sizeof( block_fifo_t ) );
-    if( !p_fifo )
-        return NULL;
 
-    vlc_mutex_init( &p_fifo->lock );
-    vlc_cond_init( &p_fifo->wait );
-    p_fifo->p_first = NULL;
-    p_fifo->pp_last = &p_fifo->p_first;
-    p_fifo->i_depth = p_fifo->i_size = 0;
+    if (likely(p_fifo != NULL)) {
+        vlc_queue_Init(&p_fifo->q);
+        p_fifo->i_depth = 0;
+        p_fifo->i_size = 0;
+    }
 
     return p_fifo;
 }
@@ -183,8 +132,8 @@ block_t *block_FifoShow( block_fifo_t *p_fifo )
     block_t *b;
 
     vlc_fifo_Lock(p_fifo);
-    assert(p_fifo->p_first != NULL);
-    b = p_fifo->p_first;
+    assert(p_fifo->q.first != NULL);
+    b = (block_t *)p_fifo->q.first;
     vlc_fifo_Unlock(p_fifo);
 
     return b;
-- 
2.26.0



More information about the vlc-devel mailing list