diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 22:58:22 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 22:58:22 +0000 |
commit | df8e899b92196a772511a165130f1fe08e199cb8 (patch) | |
tree | 893ca8821adc6165823f3c9a10dd0edfeb2e49e1 /content/browser/browser_thread.cc | |
parent | 5b77de94051020ca0aef549dee0cb33f7a737d88 (diff) | |
download | chromium_src-df8e899b92196a772511a165130f1fe08e199cb8.zip chromium_src-df8e899b92196a772511a165130f1fe08e199cb8.tar.gz chromium_src-df8e899b92196a772511a165130f1fe08e199cb8.tar.bz2 |
Move core pieces of chrome\browser. I've only gone up to "g", will do the rest in another cl.
TBR=avi
Review URL: http://codereview.chromium.org/6538100
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75652 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/browser_thread.cc')
-rw-r--r-- | content/browser/browser_thread.cc | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/content/browser/browser_thread.cc b/content/browser/browser_thread.cc new file mode 100644 index 0000000..c0e4355 --- /dev/null +++ b/content/browser/browser_thread.cc @@ -0,0 +1,233 @@ +// Copyright (c) 2010 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. + +#include "content/browser/browser_thread.h" + +#include "base/message_loop.h" +#include "base/message_loop_proxy.h" +#include "base/threading/thread_restrictions.h" + +// Friendly names for the well-known threads. +static const char* browser_thread_names[BrowserThread::ID_COUNT] = { + "", // UI (name assembled in browser_main.cc). + "Chrome_DBThread", // DB + "Chrome_WebKitThread", // WEBKIT + "Chrome_FileThread", // FILE + "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER + "Chrome_CacheThread", // CACHE + "Chrome_IOThread", // IO +#if defined(USE_X11) + "Chrome_Background_X11Thread", // BACKGROUND_X11 +#endif +}; + +// An implementation of MessageLoopProxy to be used in conjunction +// with BrowserThread. +class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { + public: + explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) + : id_(identifier) { + } + + // MessageLoopProxy implementation. + virtual bool PostTask(const tracked_objects::Location& from_here, + Task* task) { + return BrowserThread::PostTask(id_, from_here, task); + } + + virtual bool PostDelayedTask(const tracked_objects::Location& from_here, + Task* task, int64 delay_ms) { + return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms); + } + + virtual bool PostNonNestableTask(const tracked_objects::Location& from_here, + Task* task) { + return BrowserThread::PostNonNestableTask(id_, from_here, task); + } + + virtual bool PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + Task* task, + int64 delay_ms) { + return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, + delay_ms); + } + virtual bool BelongsToCurrentThread() { + return BrowserThread::CurrentlyOn(id_); + } + + private: + BrowserThread::ID id_; + DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); +}; + + +base::Lock BrowserThread::lock_; + +BrowserThread* BrowserThread::browser_threads_[ID_COUNT]; + +BrowserThread::BrowserThread(BrowserThread::ID identifier) + : Thread(browser_thread_names[identifier]), + identifier_(identifier) { + Initialize(); +} + +BrowserThread::BrowserThread(ID identifier, MessageLoop* message_loop) + : Thread(message_loop->thread_name().c_str()), + identifier_(identifier) { + set_message_loop(message_loop); + Initialize(); +} + +void BrowserThread::Initialize() { + base::AutoLock lock(lock_); + DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT); + DCHECK(browser_threads_[identifier_] == NULL); + browser_threads_[identifier_] = this; +} + +BrowserThread::~BrowserThread() { + // Stop the thread here, instead of the parent's class destructor. This is so + // that if there are pending tasks that run, code that checks that it's on the + // correct BrowserThread succeeds. + Stop(); + + base::AutoLock lock(lock_); + browser_threads_[identifier_] = NULL; +#ifndef NDEBUG + // Double check that the threads are ordered correctly in the enumeration. + for (int i = identifier_ + 1; i < ID_COUNT; ++i) { + DCHECK(!browser_threads_[i]) << + "Threads must be listed in the reverse order that they die"; + } +#endif +} + +// static +bool BrowserThread::IsWellKnownThread(ID identifier) { + base::AutoLock lock(lock_); + return (identifier >= 0 && identifier < ID_COUNT && + browser_threads_[identifier]); +} + +// static +bool BrowserThread::CurrentlyOn(ID identifier) { + // We shouldn't use MessageLoop::current() since it uses LazyInstance which + // may be deleted by ~AtExitManager when a WorkerPool thread calls this + // function. + // http://crbug.com/63678 + base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; + base::AutoLock lock(lock_); + DCHECK(identifier >= 0 && identifier < ID_COUNT); + return browser_threads_[identifier] && + browser_threads_[identifier]->message_loop() == MessageLoop::current(); +} + +// static +bool BrowserThread::IsMessageLoopValid(ID identifier) { + base::AutoLock lock(lock_); + DCHECK(identifier >= 0 && identifier < ID_COUNT); + return browser_threads_[identifier] && + browser_threads_[identifier]->message_loop(); +} + +// static +bool BrowserThread::PostTask(ID identifier, + const tracked_objects::Location& from_here, + Task* task) { + return PostTaskHelper(identifier, from_here, task, 0, true); +} + +// static +bool BrowserThread::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 BrowserThread::PostNonNestableTask( + ID identifier, + const tracked_objects::Location& from_here, + Task* task) { + return PostTaskHelper(identifier, from_here, task, 0, false); +} + +// static +bool BrowserThread::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 BrowserThread::GetCurrentThreadIdentifier(ID* identifier) { + // We shouldn't use MessageLoop::current() since it uses LazyInstance which + // may be deleted by ~AtExitManager when a WorkerPool thread calls this + // function. + // http://crbug.com/63678 + base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; + MessageLoop* cur_message_loop = MessageLoop::current(); + for (int i = 0; i < ID_COUNT; ++i) { + if (browser_threads_[i] && + browser_threads_[i]->message_loop() == cur_message_loop) { + *identifier = browser_threads_[i]->identifier_; + return true; + } + } + + return false; +} + +// static +scoped_refptr<base::MessageLoopProxy> +BrowserThread::GetMessageLoopProxyForThread( + ID identifier) { + scoped_refptr<base::MessageLoopProxy> proxy( + new BrowserThreadMessageLoopProxy(identifier)); + return proxy; +} + +// static +bool BrowserThread::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 = browser_threads_[identifier] ? + browser_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; +} |