diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-27 03:59:31 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-27 03:59:31 +0000 |
commit | d85cf074f2186dbe1cf8a9db5d89a2b817ffb0e1 (patch) | |
tree | e03156e3142955f7cf637fe404a1ce2c6f7aaaf4 /chrome/browser/chrome_thread.cc | |
parent | 76a188be4e3ddc42c42beabfeeeb618b2adae11e (diff) | |
download | chromium_src-d85cf074f2186dbe1cf8a9db5d89a2b817ffb0e1.zip chromium_src-d85cf074f2186dbe1cf8a9db5d89a2b817ffb0e1.tar.gz chromium_src-d85cf074f2186dbe1cf8a9db5d89a2b817ffb0e1.tar.bz2 |
Simplify threading in browser thread by making only ChromeThread deal with different thread lifetimes.The rest of the code doesn't get MessageLoop pointers since they're not thread-safe and instead just call PostTask on ChromeThread. If the target thread is not alive, then the task is simply deleted.In a followup change, I'll remove any remaining MessageLoop* caching. With this change, there's little to be gained by caching since no locks are involved if the target MessageLoop is guaranteed to outlive the current thread (inferred automatically by the order of the chrome_threads_ array).BUG=25354
Review URL: http://codereview.chromium.org/306032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30163 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chrome_thread.cc')
-rw-r--r-- | chrome/browser/chrome_thread.cc | 129 |
1 files changed, 101 insertions, 28 deletions
diff --git a/chrome/browser/chrome_thread.cc b/chrome/browser/chrome_thread.cc index 8cd7767..576ac77 100644 --- a/chrome/browser/chrome_thread.cc +++ b/chrome/browser/chrome_thread.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 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. @@ -7,10 +7,10 @@ // Friendly names for the well-known threads. static const char* chrome_thread_names[ChromeThread::ID_COUNT] = { "", // UI (name assembled in browser_main.cc). - "Chrome_IOThread", // IO - "Chrome_FileThread", // FILE "Chrome_DBThread", // DB "Chrome_WebKitThread", // WEBKIT + "Chrome_FileThread", // FILE + "Chrome_IOThread", // IO #if defined(OS_LINUX) "Chrome_Background_X11Thread", // BACKGROUND_X11 #endif @@ -18,16 +18,7 @@ static const char* chrome_thread_names[ChromeThread::ID_COUNT] = { Lock ChromeThread::lock_; -ChromeThread* ChromeThread::chrome_threads_[ID_COUNT] = { - NULL, // UI - NULL, // IO - NULL, // FILE - NULL, // DB - NULL, // WEBKIT -#if defined(OS_LINUX) - NULL, // BACKGROUND_X11 -#endif -}; +ChromeThread* ChromeThread::chrome_threads_[ID_COUNT]; ChromeThread::ChromeThread(ChromeThread::ID identifier) : Thread(chrome_thread_names[identifier]), @@ -35,10 +26,10 @@ ChromeThread::ChromeThread(ChromeThread::ID identifier) Initialize(); } -ChromeThread::ChromeThread() - : Thread(MessageLoop::current()->thread_name().c_str()), - identifier_(UI) { - set_message_loop(MessageLoop::current()); +ChromeThread::ChromeThread(ID identifier, MessageLoop* message_loop) + : Thread(message_loop->thread_name().c_str()), + identifier_(identifier) { + set_message_loop(message_loop); Initialize(); } @@ -52,26 +43,108 @@ void ChromeThread::Initialize() { ChromeThread::~ChromeThread() { AutoLock lock(lock_); chrome_threads_[identifier_] = NULL; +#ifndef NDEBUG + // Double check that the threads are ordererd correctly in the enumeration. + for (int i = identifier_ + 1; i < ID_COUNT; ++i) { + DCHECK(!chrome_threads_[i]) << + "Threads must be listed in the reverse order that they die"; + } +#endif } // static -MessageLoop* ChromeThread::GetMessageLoop(ID identifier) { +bool ChromeThread::CurrentlyOn(ID identifier) { + // chrome_threads_[identifier] will be NULL if none is running. This is often + // true when running under unit tests. This behavior actually works out + // pretty conveniently but it's worth noting here. AutoLock lock(lock_); DCHECK(identifier >= 0 && identifier < ID_COUNT); + return chrome_threads_[identifier] && + chrome_threads_[identifier]->message_loop() == MessageLoop::current(); +} - if (chrome_threads_[identifier]) - return chrome_threads_[identifier]->message_loop(); +// static +bool ChromeThread::PostTask(ID identifier, + const tracked_objects::Location& from_here, + Task* task) { + return PostTaskHelper(identifier, from_here, task, 0, true); +} - return NULL; +// static +bool ChromeThread::PostDelayedTask(ID identifier, + const tracked_objects::Location& from_here, + Task* task, + int64 delay_ms) { + return PostTaskHelper(identifier, from_here, task, delay_ms, true); } // static -bool ChromeThread::CurrentlyOn(ID identifier) { - // MessageLoop::current() will return NULL if none is running. This is often - // true when running under unit tests. This behavior actually works out - // pretty convienently (as is mentioned in the header file comment), but it's - // worth noting here. - MessageLoop* message_loop = GetMessageLoop(identifier); - return MessageLoop::current() == message_loop; +bool ChromeThread::PostNonNestableTask( + ID identifier, + const tracked_objects::Location& from_here, + Task* task) { + return PostTaskHelper(identifier, from_here, task, 0, false); +} + +// static +bool ChromeThread::PostNonNestableDelayedTask( + ID identifier, + const tracked_objects::Location& from_here, + Task* task, + int64 delay_ms) { + return PostTaskHelper(identifier, from_here, task, delay_ms, false); +} + +// static +bool ChromeThread::GetCurrentThreadIdentifier(ID* identifier) { + MessageLoop* cur_message_loop = MessageLoop::current(); + for (int i = 0; i < ID_COUNT; ++i) { + if (chrome_threads_[i] && + chrome_threads_[i]->message_loop() == cur_message_loop) { + *identifier = chrome_threads_[i]->identifier_; + return true; + } + } + + return false; } +// static +bool ChromeThread::PostTaskHelper( + ID identifier, + const tracked_objects::Location& from_here, + Task* task, + int64 delay_ms, + bool nestable) { + DCHECK(identifier >= 0 && identifier < ID_COUNT); + // Optimization: to avoid unnecessary locks, we listed the ID enumeration in + // order of lifetime. So no need to lock if we know that the other thread + // outlives this one. + // Note: since the array is so small, ok to loop instead of creating a map, + // which would require a lock because std::map isn't thread safe, defeating + // the whole purpose of this optimization. + ID current_thread; + bool guaranteed_to_outlive_target_thread = + GetCurrentThreadIdentifier(¤t_thread) && + current_thread >= identifier; + + if (!guaranteed_to_outlive_target_thread) + lock_.Acquire(); + + MessageLoop* message_loop = chrome_threads_[identifier] ? + chrome_threads_[identifier]->message_loop() : NULL; + if (message_loop) { + if (nestable) { + message_loop->PostDelayedTask(from_here, task, delay_ms); + } else { + message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms); + } + } else { + delete task; + } + + if (!guaranteed_to_outlive_target_thread) + lock_.Release(); + + return !!message_loop; +} |