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