// Copyright 2015 The Chromium OS 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 <brillo/message_loops/message_loop.h>
#include <base/lazy_instance.h>
#include <base/logging.h>
#include <base/threading/thread_local.h>
namespace brillo {
namespace {
// A lazily created thread local storage for quick access to a thread's message
// loop, if one exists. This should be safe and free of static constructors.
base::LazyInstance<base::ThreadLocalPointer<MessageLoop> >::Leaky lazy_tls_ptr =
LAZY_INSTANCE_INITIALIZER;
} // namespace
const MessageLoop::TaskId MessageLoop::kTaskIdNull = 0;
MessageLoop* MessageLoop::current() {
DCHECK(lazy_tls_ptr.Pointer()->Get() != nullptr) <<
"There isn't a MessageLoop for this thread. You need to initialize it "
"first.";
return lazy_tls_ptr.Pointer()->Get();
}
bool MessageLoop::ThreadHasCurrent() {
return lazy_tls_ptr.Pointer()->Get() != nullptr;
}
void MessageLoop::SetAsCurrent() {
DCHECK(lazy_tls_ptr.Pointer()->Get() == nullptr) <<
"There's already a MessageLoop for this thread.";
lazy_tls_ptr.Pointer()->Set(this);
}
void MessageLoop::ReleaseFromCurrent() {
DCHECK(lazy_tls_ptr.Pointer()->Get() == this) <<
"This is not the MessageLoop bound to the current thread.";
lazy_tls_ptr.Pointer()->Set(nullptr);
}
MessageLoop::~MessageLoop() {
if (lazy_tls_ptr.Pointer()->Get() == this)
lazy_tls_ptr.Pointer()->Set(nullptr);
}
void MessageLoop::Run() {
// Default implementation is to call RunOnce() blocking until there aren't
// more tasks scheduled.
while (!should_exit_ && RunOnce(true)) {}
should_exit_ = false;
}
void MessageLoop::BreakLoop() {
should_exit_ = true;
}
} // namespace brillo