Fix for indefinite blockage in TaskRunnerImpl.

Change-Id: Id11a097e2376e42093d9c721ffd0a9e1a22885c2
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/1825871
Commit-Queue: Yuri Wiitala <miu@chromium.org>
Reviewed-by: Max Yakimakha <yakimakha@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
diff --git a/platform/impl/task_runner.cc b/platform/impl/task_runner.cc
index 7323c47..9bacacf 100644
--- a/platform/impl/task_runner.cc
+++ b/platform/impl/task_runner.cc
@@ -19,7 +19,10 @@
       task_waiter_(event_waiter),
       waiter_timeout_(waiter_timeout) {}
 
-TaskRunnerImpl::~TaskRunnerImpl() = default;
+TaskRunnerImpl::~TaskRunnerImpl() {
+  // Ensure no thread is currently executing inside RunUntilStopped().
+  OSP_DCHECK_EQ(task_runner_thread_id_, std::thread::id());
+}
 
 void TaskRunnerImpl::PostPackagedTask(Task task) {
   std::lock_guard<std::mutex> lock(task_mutex_);
@@ -48,7 +51,7 @@
 }
 
 void TaskRunnerImpl::RunUntilStopped() {
-  OSP_CHECK(!is_running_);
+  OSP_DCHECK(!is_running_);
   task_runner_thread_id_ = std::this_thread::get_id();
   is_running_ = true;
 
@@ -104,19 +107,6 @@
   delayed_tasks_.erase(delayed_tasks_.begin(), end_of_range);
 }
 
-bool TaskRunnerImpl::ShouldWakeUpRunLoop() {
-  if (!is_running_) {
-    return true;
-  }
-
-  if (!tasks_.empty()) {
-    return true;
-  }
-
-  return !delayed_tasks_.empty() &&
-         (delayed_tasks_.begin()->first <= now_function_());
-}
-
 bool TaskRunnerImpl::GrabMoreRunnableTasks() {
   OSP_DCHECK(running_tasks_.empty());
 
@@ -131,36 +121,25 @@
   }
 
   if (task_waiter_) {
-    do {
-      Clock::duration timeout = waiter_timeout_;
-      if (!delayed_tasks_.empty()) {
-        Clock::duration next_task_delta =
-            delayed_tasks_.begin()->first - now_function_();
-        if (next_task_delta < timeout) {
-          timeout = next_task_delta;
-        }
-      }
-      lock.unlock();
-      task_waiter_->WaitForTaskToBePosted(timeout);
-      lock.lock();
-    } while (!ShouldWakeUpRunLoop());
-  } else {
-    // Pass a wait predicate to avoid lost or spurious wakeups.
-    const auto wait_predicate = [this] { return ShouldWakeUpRunLoop(); };
+    Clock::duration timeout = waiter_timeout_;
     if (!delayed_tasks_.empty()) {
-      // We don't have any work to do currently, but have some in the
-      // pipe.
-      OSP_DVLOG << "TaskRunner waiting for lock until delayed task ready...";
-      run_loop_wakeup_.wait_for(lock,
-                                delayed_tasks_.begin()->first - now_function_(),
-                                wait_predicate);
-    } else {
-      // We don't have any work queued.
-      OSP_DVLOG << "TaskRunnerImpl waiting for lock...";
-      run_loop_wakeup_.wait(lock, wait_predicate);
+      Clock::duration next_task_delta =
+          delayed_tasks_.begin()->first - now_function_();
+      if (next_task_delta < timeout) {
+        timeout = next_task_delta;
+      }
     }
+    lock.unlock();
+    task_waiter_->WaitForTaskToBePosted(timeout);
+    return false;
   }
 
+  if (delayed_tasks_.empty()) {
+    run_loop_wakeup_.wait(lock);
+  } else {
+    run_loop_wakeup_.wait_for(lock,
+                              delayed_tasks_.begin()->first - now_function_());
+  }
   return false;
 }