1// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <brillo/message_loops/message_loop.h>
6
7#include <base/lazy_instance.h>
8#include <base/logging.h>
9#include <base/threading/thread_local.h>
10
11namespace brillo {
12
13namespace {
14
15// A lazily created thread local storage for quick access to a thread's message
16// loop, if one exists.  This should be safe and free of static constructors.
17base::LazyInstance<base::ThreadLocalPointer<MessageLoop> >::Leaky lazy_tls_ptr =
18    LAZY_INSTANCE_INITIALIZER;
19
20}  // namespace
21
22const MessageLoop::TaskId MessageLoop::kTaskIdNull = 0;
23
24MessageLoop* MessageLoop::current() {
25  DCHECK(lazy_tls_ptr.Pointer()->Get() != nullptr) <<
26      "There isn't a MessageLoop for this thread. You need to initialize it "
27      "first.";
28  return lazy_tls_ptr.Pointer()->Get();
29}
30
31bool MessageLoop::ThreadHasCurrent() {
32  return lazy_tls_ptr.Pointer()->Get() != nullptr;
33}
34
35void MessageLoop::SetAsCurrent() {
36  DCHECK(lazy_tls_ptr.Pointer()->Get() == nullptr) <<
37      "There's already a MessageLoop for this thread.";
38  lazy_tls_ptr.Pointer()->Set(this);
39}
40
41void MessageLoop::ReleaseFromCurrent() {
42  DCHECK(lazy_tls_ptr.Pointer()->Get() == this) <<
43      "This is not the MessageLoop bound to the current thread.";
44  lazy_tls_ptr.Pointer()->Set(nullptr);
45}
46
47MessageLoop::~MessageLoop() {
48  if (lazy_tls_ptr.Pointer()->Get() == this)
49    lazy_tls_ptr.Pointer()->Set(nullptr);
50}
51
52void MessageLoop::Run() {
53  // Default implementation is to call RunOnce() blocking until there aren't
54  // more tasks scheduled.
55  while (!should_exit_ && RunOnce(true)) {}
56  should_exit_ = false;
57}
58
59void MessageLoop::BreakLoop() {
60  should_exit_ = true;
61}
62
63}  // namespace brillo
64