summaryrefslogtreecommitdiffstats
path: root/content/browser/browser_thread_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'content/browser/browser_thread_impl.cc')
-rw-r--r--content/browser/browser_thread_impl.cc160
1 files changed, 90 insertions, 70 deletions
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 023259b..0025f77 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -4,16 +4,19 @@
#include "content/browser/browser_thread_impl.h"
+#include "base/atomicops.h"
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/threading/thread_restrictions.h"
+namespace content {
+
namespace {
// Friendly names for the well-known threads.
-static const char* browser_thread_names[content::BrowserThread::ID_COUNT] = {
+static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = {
"", // UI (name assembled in browser_main.cc).
"Chrome_DBThread", // DB
"Chrome_WebKitThread", // WEBKIT
@@ -26,38 +29,86 @@ static const char* browser_thread_names[content::BrowserThread::ID_COUNT] = {
#endif
};
-} // namespace
-
-namespace content {
-
-namespace {
-
-// This lock protects |g_browser_threads|. Do not read or modify that array
-// without holding this lock. Do not block while holding this lock.
+// This lock protects |g_browser_threads|. Do not read or modify that
+// array without holding this lock. Do not block while holding this
+// lock.
base::LazyInstance<base::Lock,
base::LeakyLazyInstanceTraits<base::Lock> >
g_lock = LAZY_INSTANCE_INITIALIZER;
-
-// An array of the BrowserThread objects. This array is protected by |g_lock|.
-// The threads are not owned by this array. Typically, the threads are owned
-// on the UI thread by the g_browser_process object. BrowserThreads remove
+// This array is protected by |g_lock|. The threads are not owned by this
+// array. Typically, the threads are owned on the UI thread by
+// content::BrowserMainLoop. BrowserThreadImpl objects remove
// themselves from this array upon destruction.
-BrowserThread* g_browser_threads[BrowserThread::ID_COUNT];
+static BrowserThreadImpl* g_browser_threads[BrowserThread::ID_COUNT];
+
+// Only atomic operations are used on this array. The delegates are
+// not owned by this array, rather by whoever calls
+// BrowserThread::SetDelegate.
+static BrowserThreadDelegate* g_browser_thread_delegates[
+ BrowserThread::ID_COUNT];
} // namespace
-BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier)
- : BrowserThread(identifier) {
+BrowserThreadImpl::BrowserThreadImpl(ID identifier)
+ : Thread(g_browser_thread_names[identifier]),
+ identifier_(identifier) {
+ Initialize();
}
-BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier,
+BrowserThreadImpl::BrowserThreadImpl(ID identifier,
MessageLoop* message_loop)
- : BrowserThread(identifier, message_loop) {
+ : Thread(message_loop->thread_name().c_str()),
+ identifier_(identifier) {
+ set_message_loop(message_loop);
+ Initialize();
+}
+
+void BrowserThreadImpl::Init() {
+ using base::subtle::AtomicWord;
+ AtomicWord* storage =
+ reinterpret_cast<AtomicWord*>(&g_browser_thread_delegates[identifier_]);
+ AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
+ BrowserThreadDelegate* delegate =
+ reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
+ if (delegate)
+ delegate->Init();
+}
+
+void BrowserThreadImpl::CleanUp() {
+ using base::subtle::AtomicWord;
+ AtomicWord* storage =
+ reinterpret_cast<AtomicWord*>(&g_browser_thread_delegates[identifier_]);
+ AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
+ BrowserThreadDelegate* delegate =
+ reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
+
+ if (delegate)
+ delegate->CleanUp();
+}
+
+void BrowserThreadImpl::Initialize() {
+ base::AutoLock lock(g_lock.Get());
+ DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
+ DCHECK(g_browser_threads[identifier_] == NULL);
+ g_browser_threads[identifier_] = this;
}
BrowserThreadImpl::~BrowserThreadImpl() {
+ // All Thread subclasses must call Stop() in the destructor. This is
+ // doubly important here as various bits of code check they are on
+ // the right BrowserThread.
Stop();
+
+ base::AutoLock lock(g_lock.Get());
+ g_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(!g_browser_threads[i]) <<
+ "Threads must be listed in the reverse order that they die";
+ }
+#endif
}
// static
@@ -77,7 +128,7 @@ bool BrowserThreadImpl::PostTaskHelper(
BrowserThread::ID current_thread;
bool guaranteed_to_outlive_target_thread =
GetCurrentThreadIdentifier(&current_thread) &&
- current_thread >= identifier;
+ current_thread <= identifier;
if (!guaranteed_to_outlive_target_thread)
g_lock.Get().Acquire();
@@ -118,7 +169,7 @@ bool BrowserThreadImpl::PostTaskHelper(
BrowserThread::ID current_thread;
bool guaranteed_to_outlive_target_thread =
GetCurrentThreadIdentifier(&current_thread) &&
- current_thread >= identifier;
+ current_thread <= identifier;
if (!guaranteed_to_outlive_target_thread)
g_lock.Get().Acquire();
@@ -139,18 +190,6 @@ bool BrowserThreadImpl::PostTaskHelper(
return !!message_loop;
}
-// TODO(joi): Remove
-DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier)
- : BrowserThread(identifier) {
-}
-DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier,
- MessageLoop* message_loop)
- : BrowserThread(identifier, message_loop) {
-}
-DeprecatedBrowserThread::~DeprecatedBrowserThread() {
- Stop();
-}
-
// An implementation of MessageLoopProxy to be used in conjunction
// with BrowserThread.
class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
@@ -215,44 +254,6 @@ class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy);
};
-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(g_lock.Get());
- DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
- DCHECK(g_browser_threads[identifier_] == NULL);
- g_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(g_lock.Get());
- g_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(!g_browser_threads[i]) <<
- "Threads must be listed in the reverse order that they die";
- }
-#endif
-}
-
// static
bool BrowserThread::IsWellKnownThread(ID identifier) {
base::AutoLock lock(g_lock.Get());
@@ -393,4 +394,23 @@ BrowserThread::GetMessageLoopProxyForThread(
return proxy;
}
+base::Thread* BrowserThread::UnsafeGetBrowserThread(ID identifier) {
+ base::AutoLock lock(g_lock.Get());
+ base::Thread* thread = g_browser_threads[identifier];
+ DCHECK(thread);
+ return thread;
+}
+
+void BrowserThread::SetDelegate(ID identifier,
+ BrowserThreadDelegate* delegate) {
+ using base::subtle::AtomicWord;
+ AtomicWord* storage = reinterpret_cast<AtomicWord*>(
+ &g_browser_thread_delegates[identifier]);
+ AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange(
+ storage, reinterpret_cast<AtomicWord>(delegate));
+
+ // This catches registration when previously registered.
+ DCHECK(!delegate || !old_pointer);
+}
+
} // namespace content