Index: content/browser/browser_thread_impl.cc |
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc |
index 023259bcc7deaf807447056b8cc0bf7d409fe847..0025f77841e1dd57cc876c0d3bd2eda13a4ee443 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(¤t_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(¤t_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 |