Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(814)

Unified Diff: base/threading/thread.cc

Issue 2145463002: Modernize base::Thread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comment nit Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/threading/thread.h ('k') | base/threading/thread_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/threading/thread.cc
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index a8833aeb3f39b553d15d41f66737b7d83bfcad54..98610a63c09875878ffceca6417d7af16980ca89 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -33,42 +33,26 @@ base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool =
} // namespace
-Thread::Options::Options()
- : message_loop_type(MessageLoop::TYPE_DEFAULT),
- timer_slack(TIMER_SLACK_NONE),
- stack_size(0),
- priority(ThreadPriority::NORMAL) {
-}
+Thread::Options::Options() = default;
-Thread::Options::Options(MessageLoop::Type type,
- size_t size)
- : message_loop_type(type),
- timer_slack(TIMER_SLACK_NONE),
- stack_size(size),
- priority(ThreadPriority::NORMAL) {
-}
+Thread::Options::Options(MessageLoop::Type type, size_t size)
+ : message_loop_type(type), stack_size(size) {}
Thread::Options::Options(const Options& other) = default;
-Thread::Options::~Options() {
-}
+Thread::Options::~Options() = default;
Thread::Thread(const std::string& name)
- :
-#if defined(OS_WIN)
- com_status_(NONE),
-#endif
- stopping_(false),
- running_(false),
- thread_(0),
- id_(kInvalidThreadId),
- id_event_(WaitableEvent::ResetPolicy::MANUAL,
+ : id_event_(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED),
- message_loop_(nullptr),
- message_loop_timer_slack_(TIMER_SLACK_NONE),
name_(name),
start_event_(WaitableEvent::ResetPolicy::MANUAL,
WaitableEvent::InitialState::NOT_SIGNALED) {
+ // Only bind the sequence on Start(): the state is constant between
+ // construction and Start() and it's thus valid for Start() to be called on
+ // another sequence as long as every other operation is then performed on that
+ // sequence.
+ owning_sequence_checker_.DetachFromSequence();
}
Thread::~Thread() {
@@ -76,6 +60,8 @@ Thread::~Thread() {
}
bool Thread::Start() {
+ DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
+
Options options;
#if defined(OS_WIN)
if (com_status_ == STA)
@@ -85,7 +71,9 @@ bool Thread::Start() {
}
bool Thread::StartWithOptions(const Options& options) {
+ DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
DCHECK(!message_loop_);
+ DCHECK(!IsRunning());
#if defined(OS_WIN)
DCHECK((com_status_ != STA) ||
(options.message_loop_type == MessageLoop::TYPE_UI));
@@ -102,13 +90,14 @@ bool Thread::StartWithOptions(const Options& options) {
type = MessageLoop::TYPE_CUSTOM;
message_loop_timer_slack_ = options.timer_slack;
- std::unique_ptr<MessageLoop> message_loop =
+ std::unique_ptr<MessageLoop> message_loop_owned =
MessageLoop::CreateUnbound(type, options.message_pump_factory);
- message_loop_ = message_loop.get();
+ message_loop_ = message_loop_owned.get();
start_event_.Reset();
- // Hold the thread_lock_ while starting a new thread, so that we can make sure
- // that thread_ is populated before the newly created thread accesses it.
+ // Hold |thread_lock_| while starting the new thread to synchronize with
+ // Stop() while it's not guaranteed to be sequenced (until crbug/629139 is
+ // fixed).
{
AutoLock lock(thread_lock_);
if (!PlatformThread::CreateWithPriority(options.stack_size, this, &thread_,
@@ -119,15 +108,16 @@ bool Thread::StartWithOptions(const Options& options) {
}
}
- // The ownership of message_loop is managemed by the newly created thread
+ // The ownership of |message_loop_| is managed by the newly created thread
// within the ThreadMain.
- ignore_result(message_loop.release());
+ ignore_result(message_loop_owned.release());
DCHECK(message_loop_);
return true;
}
bool Thread::StartAndWaitForTesting() {
+ DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
bool result = Start();
if (!result)
return false;
@@ -136,6 +126,7 @@ bool Thread::StartAndWaitForTesting() {
}
bool Thread::WaitUntilThreadStarted() const {
+ DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
if (!message_loop_)
return false;
base::ThreadRestrictions::ScopedAllowWait allow_wait;
@@ -144,7 +135,12 @@ bool Thread::WaitUntilThreadStarted() const {
}
void Thread::Stop() {
+ // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+ // enable this check, until then synchronization with Start() via
+ // |thread_lock_| is required...
Wez 2016/07/25 21:20:29 FWIW, this comment as worded implies that callers
gab 2016/07/26 02:48:23 Generally in Chromium, unless specified otherwise,
+ // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
AutoLock lock(thread_lock_);
+
if (thread_.is_null())
return;
@@ -152,22 +148,23 @@ void Thread::Stop() {
// Wait for the thread to exit.
//
- // TODO(darin): Unfortunately, we need to keep message_loop_ around until
+ // TODO(darin): Unfortunately, we need to keep |message_loop_| around until
// the thread exits. Some consumers are abusing the API. Make them stop.
//
PlatformThread::Join(thread_);
thread_ = base::PlatformThreadHandle();
- // The thread should nullify message_loop_ on exit.
+ // The thread should nullify |message_loop_| on exit (note: Join() adds an
+ // implicit memory barrier and no lock is thus required for this check).
DCHECK(!message_loop_);
stopping_ = false;
}
void Thread::StopSoon() {
- // We should only be called on the same thread that started us.
-
- DCHECK_NE(GetThreadId(), PlatformThread::CurrentId());
+ // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+ // enable this check.
+ // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
if (stopping_ || !message_loop_)
return;
@@ -185,26 +182,35 @@ PlatformThreadId Thread::GetThreadId() const {
}
bool Thread::IsRunning() const {
- // If the thread's already started (i.e. message_loop_ is non-null) and
- // not yet requested to stop (i.e. stopping_ is false) we can just return
- // true. (Note that stopping_ is touched only on the same thread that
- // starts / started the new thread so we need no locking here.)
+ // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+ // enable this check.
+ // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
+
+ // If the thread's already started (i.e. |message_loop_| is non-null) and not
+ // yet requested to stop (i.e. |stopping_| is false) we can just return true.
+ // (Note that |stopping_| is touched only on the same sequence that starts /
+ // started the new thread so we need no locking here.)
if (message_loop_ && !stopping_)
return true;
- // Otherwise check the running_ flag, which is set to true by the new thread
+ // Otherwise check the |running_| flag, which is set to true by the new thread
// only while it is inside Run().
AutoLock lock(running_lock_);
return running_;
}
void Thread::Run(RunLoop* run_loop) {
+ // Overridable protected method to be called from our |thread_| only.
+ DCHECK_EQ(id_, PlatformThread::CurrentId());
Wez 2016/07/25 21:22:36 What is this DCHECK intended to protect against? C
gab 2016/07/26 02:48:23 As is often the case with DCHECKs, it's intended a
+
run_loop->Run();
}
+// static
void Thread::SetThreadWasQuitProperly(bool flag) {
lazy_tls_bool.Pointer()->Set(flag);
}
+// static
bool Thread::GetThreadWasQuitProperly() {
bool quit_properly = true;
#ifndef NDEBUG
@@ -224,7 +230,7 @@ void Thread::ThreadMain() {
PlatformThread::SetName(name_.c_str());
ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector.
- // Lazily initialize the message_loop so that it can run on this thread.
+ // Lazily initialize the |message_loop| so that it can run on this thread.
DCHECK(message_loop_);
std::unique_ptr<MessageLoop> message_loop(message_loop_);
message_loop_->BindToCurrentThread();
« no previous file with comments | « base/threading/thread.h ('k') | base/threading/thread_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698