]> git.sesse.net Git - vlc/commitdiff
Android: remove contention in vlc_cond_wait()
authorRémi Denis-Courmont <remi@remlab.net>
Mon, 15 Oct 2012 18:16:04 +0000 (21:16 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Tue, 16 Oct 2012 15:21:38 +0000 (18:21 +0300)
src/android/thread.c

index 0294baa7ae335586c5e1614f9099556e3a43bd44..10380cb6e680ca868e4fb83690c7f9ddb3e8f9ca 100644 (file)
@@ -216,36 +216,65 @@ void vlc_cond_broadcast (vlc_cond_t *condvar)
 
 void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex)
 {
-    if (thread) {
-        vlc_testcancel();
-        vlc_mutex_lock(&thread->lock);
-        thread->cond = &condvar->cond;
-        vlc_mutex_unlock(&thread->lock);
+    vlc_thread_t th = thread;
+
+    if (th != NULL)
+    {
+        vlc_testcancel ();
+        if (vlc_mutex_trylock (&th->lock) == 0)
+        {
+            th->cond = &condvar->cond;
+            vlc_mutex_unlock (&th->lock);
+        }
+        else
+        {   /* The lock is already held by another thread.
+             * => That other thread has just cancelled this one. */
+            vlc_testcancel ();
+            /* Cancellation did not occur even though this thread is cancelled.
+             * => Cancellation is disabled. */
+            th = NULL;
+        }
     }
 
     int val = pthread_cond_wait (&condvar->cond, p_mutex);
+    VLC_THREAD_ASSERT ("waiting on condition");
 
-    if (thread) {
-        vlc_mutex_lock(&thread->lock);
-        thread->cond = NULL;
-        vlc_mutex_unlock(&thread->lock);
+    if (th != NULL)
+    {
+        if (vlc_mutex_trylock (&th->lock) == 0)
+        {
+            thread->cond = NULL;
+            vlc_mutex_unlock (&th->lock);
+        }
+        /* Else: This thread was cancelled and is cancellable.
+                 vlc_testcancel() will take of it right there: */
         vlc_testcancel();
     }
-
-    VLC_THREAD_ASSERT ("waiting on condition");
 }
 
 int vlc_cond_timedwait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex,
                         mtime_t deadline)
 {
     struct timespec ts = mtime_to_ts (deadline);
+    vlc_thread_t th = thread;
     int (*cb)(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
 
-    if (thread) {
-        vlc_testcancel();
-        vlc_mutex_lock(&thread->lock);
-        thread->cond = &condvar->cond;
-        vlc_mutex_unlock(&thread->lock);
+    if (th != NULL)
+    {
+        vlc_testcancel ();
+        if (vlc_mutex_trylock (&th->lock) == 0)
+        {
+            th->cond = &condvar->cond;
+            vlc_mutex_unlock (&th->lock);
+        }
+        else
+        {   /* The lock is already held by another thread.
+             * => That other thread has just cancelled this one. */
+            vlc_testcancel ();
+            /* Cancellation did not occur even though this thread is cancelled.
+             * => Cancellation is disabled. */
+            th = NULL;
+        }
     }
 
     switch (condvar->clock)
@@ -264,13 +293,17 @@ int vlc_cond_timedwait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex,
     if (val != ETIMEDOUT)
         VLC_THREAD_ASSERT ("timed-waiting on condition");
 
-    if (thread) {
-        vlc_mutex_lock(&thread->lock);
-        thread->cond = NULL;
-        vlc_mutex_unlock(&thread->lock);
+    if (th != NULL)
+    {
+        if (vlc_mutex_trylock (&th->lock) == 0)
+        {
+            thread->cond = NULL;
+            vlc_mutex_unlock (&th->lock);
+        }
+        /* Else: This thread was cancelled and is cancellable.
+                 vlc_testcancel() will take of it right there: */
         vlc_testcancel();
     }
-
     return val;
 }