| // Copyright 2018 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "util/msg_loop.h" | 
 |  | 
 | #include "base/logging.h" | 
 |  | 
 | namespace { | 
 |  | 
 | thread_local MsgLoop* g_current; | 
 | } | 
 |  | 
 | MsgLoop::MsgLoop() { | 
 |   DCHECK(g_current == nullptr); | 
 |   g_current = this; | 
 | } | 
 |  | 
 | MsgLoop::~MsgLoop() { | 
 |   DCHECK(g_current == this); | 
 |   g_current = nullptr; | 
 | } | 
 |  | 
 | void MsgLoop::Run() { | 
 |   while (!should_quit_) { | 
 |     std::function<void()> task; | 
 |     { | 
 |       std::unique_lock<std::mutex> queue_lock(queue_mutex_); | 
 |       notifier_.wait(queue_lock, [this]() { | 
 |         return (!task_queue_.empty()) || should_quit_; | 
 |       }); | 
 |  | 
 |       if (should_quit_) | 
 |         return; | 
 |  | 
 |       task = std::move(task_queue_.front()); | 
 |       task_queue_.pop(); | 
 |     } | 
 |  | 
 |     task(); | 
 |   } | 
 | } | 
 |  | 
 | void MsgLoop::PostQuit() { | 
 |   PostTask([this]() { should_quit_ = true; }); | 
 | } | 
 |  | 
 | void MsgLoop::PostTask(std::function<void()> work) { | 
 |   { | 
 |     std::unique_lock<std::mutex> queue_lock(queue_mutex_); | 
 |     task_queue_.emplace(std::move(work)); | 
 |   } | 
 |  | 
 |   notifier_.notify_one(); | 
 | } | 
 |  | 
 | void MsgLoop::RunUntilIdleForTesting() { | 
 |   for (bool done = false; !done;) { | 
 |     std::function<void()> task; | 
 |     { | 
 |       std::unique_lock<std::mutex> queue_lock(queue_mutex_); | 
 |       task = std::move(task_queue_.front()); | 
 |       task_queue_.pop(); | 
 |  | 
 |       if (task_queue_.empty()) | 
 |         done = true; | 
 |     } | 
 |  | 
 |     task(); | 
 |   } | 
 | } | 
 |  | 
 | MsgLoop* MsgLoop::Current() { | 
 |   return g_current; | 
 | } |