[vlc-commits] background_worker: wait a little before destroying the current thread

Thomas Guillem git at videolan.org
Mon Oct 9 09:53:14 CEST 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Fri Oct  6 17:16:53 2017 +0200| [752c4964ab353b8cdfb332e3540e937547c321e9] | committer: Thomas Guillem

background_worker: wait a little before destroying the current thread

This allows to use the same thread when input are parsed sequentially (and this
avoids creating 3 threads (parser/fetcher/downloader) for each inputs). The
performance gain is not visible on Linux but can be significant on platforms
with poor thread support.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=752c4964ab353b8cdfb332e3540e937547c321e9
---

 src/misc/background_worker.c | 46 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/misc/background_worker.c b/src/misc/background_worker.c
index 70902e5b64..95ff7dcc44 100644
--- a/src/misc/background_worker.c
+++ b/src/misc/background_worker.c
@@ -20,6 +20,7 @@
 #  include "config.h"
 #endif
 
+#include <assert.h>
 #include <vlc_common.h>
 #include <vlc_threads.h>
 #include <vlc_arrays.h>
@@ -48,6 +49,7 @@ struct background_worker {
     } head;
 
     struct {
+        vlc_cond_t wait; /**< wait for update in terms of tail */
         vlc_array_t data; /**< queue of pending entities to process */
     } tail;
 };
@@ -62,6 +64,7 @@ static void* Thread( void* data )
         void* handle;
 
         vlc_mutex_lock( &worker->lock );
+        for( ;; )
         {
             if( vlc_array_count( &worker->tail.data ) )
             {
@@ -71,18 +74,43 @@ static void* Thread( void* data )
                 vlc_array_remove( &worker->tail.data, 0 );
             }
 
-            worker->head.deadline = INT64_MAX;
-            worker->head.active = item != NULL;
+            if( worker->head.deadline == VLC_TS_0 && item == NULL )
+                worker->head.active = false;
             worker->head.id = item ? item->id : NULL;
-
-            if( item && item->timeout > 0 )
-                worker->head.deadline = mdate() + item->timeout * 1000;
             vlc_cond_broadcast( &worker->head.wait );
+
+            if( item )
+            {
+                if( item->timeout > 0 )
+                    worker->head.deadline = mdate() + item->timeout * 1000;
+                else
+                    worker->head.deadline = INT64_MAX;
+            }
+            else if( worker->head.deadline != VLC_TS_0 )
+            {
+                /* Wait 1 seconds for new inputs before terminating */
+                mtime_t deadline = mdate() + INT64_C(1000000);
+                int ret = vlc_cond_timedwait( &worker->tail.wait,
+                                              &worker->lock, deadline );
+                if( ret != 0 )
+                {
+                    /* Timeout: if there is still no items, the thread will be
+                     * terminated at next loop iteration (active = false). */
+                    worker->head.deadline = VLC_TS_0;
+                }
+                continue;
+            }
+            break;
         }
-        vlc_mutex_unlock( &worker->lock );
 
-        if( item == NULL )
+        if( !worker->head.active )
+        {
+            vlc_mutex_unlock( &worker->lock );
             break;
+        }
+        vlc_mutex_unlock( &worker->lock );
+
+        assert( item != NULL );
 
         if( worker->conf.pf_start( worker->owner, item->entity, &handle ) )
         {
@@ -147,6 +175,7 @@ static void BackgroundWorkerCancel( struct background_worker* worker, void* id)
     {
         worker->head.deadline = VLC_TS_0;
         vlc_cond_signal( &worker->head.worker_wait );
+        vlc_cond_signal( &worker->tail.wait );
         vlc_cond_wait( &worker->head.wait, &worker->lock );
     }
     vlc_mutex_unlock( &worker->lock );
@@ -171,6 +200,7 @@ struct background_worker* background_worker_New( void* owner,
     vlc_cond_init( &worker->head.worker_wait );
 
     vlc_array_init( &worker->tail.data );
+    vlc_cond_init( &worker->tail.wait );
 
     return worker;
 }
@@ -189,6 +219,7 @@ int background_worker_Push( struct background_worker* worker, void* entity,
 
     vlc_mutex_lock( &worker->lock );
     vlc_array_append( &worker->tail.data, item );
+    vlc_cond_signal( &worker->tail.wait );
 
     if( worker->head.active == false )
     {
@@ -226,5 +257,6 @@ void background_worker_Delete( struct background_worker* worker )
     vlc_mutex_destroy( &worker->lock );
     vlc_cond_destroy( &worker->head.wait );
     vlc_cond_destroy( &worker->head.worker_wait );
+    vlc_cond_destroy( &worker->tail.wait );
     free( worker );
 }



More information about the vlc-commits mailing list