Index: chrome/browser/sync/weak_handle.h |
diff --git a/chrome/browser/sync/weak_handle.h b/chrome/browser/sync/weak_handle.h |
index 7c8c240183229033658440e9539325ffb46f288f..d0324dbb76a190af72165170f33cbf33653a5595 100644 |
--- a/chrome/browser/sync/weak_handle.h |
+++ b/chrome/browser/sync/weak_handle.h |
@@ -57,9 +57,13 @@ |
#include "base/logging.h" |
#include "base/memory/ref_counted.h" |
#include "base/memory/weak_ptr.h" |
-#include "base/message_loop_proxy.h" |
+#include "base/message_loop.h" |
#include "base/tracked.h" |
+namespace base { |
+class MessageLoopProxy; |
+} // namespace base |
+ |
namespace tracked_objects { |
class Location; |
} // namespace tracked_objects |
@@ -94,59 +98,83 @@ struct ParamTraits<T[]> { |
typedef const T* ForwardType; |
}; |
+class WeakHandleCoreBase; |
+ |
+struct WeakHandleCoreBaseTraits { |
+ static void Destruct(const WeakHandleCoreBase* core_base); |
+}; |
+ |
// Base class for WeakHandleCore<T> to avoid template bloat. Handles |
-// the trampolining to the MessageLoopProxy for the owner thread. |
-// |
-// This class is thread-safe. |
-class WeakHandleCoreBase { |
+// the interaction with the owner thread and its message loop. |
+class WeakHandleCoreBase |
+ : public MessageLoop::DestructionObserver, |
+ public base::RefCountedThreadSafe<WeakHandleCoreBase, |
+ WeakHandleCoreBaseTraits> { |
public: |
// Assumes the current thread is the owner thread. |
WeakHandleCoreBase(); |
+ // May be called on any thread. |
bool IsOnOwnerThread() const; |
- protected: |
- ~WeakHandleCoreBase(); |
+ // MessageLoop::DestructionObserver implementation. Must be called |
+ // on the owner thread. |
+ virtual void WillDestroyCurrentMessageLoop() OVERRIDE; |
- void PostOnOwnerThread(const tracked_objects::Location& from_here, |
+ protected: |
+ // May be deleted on any thread, but only via DestroyAndDelete() |
+ // which is called by our traits class. |
+ virtual ~WeakHandleCoreBase(); |
+ |
+ // This is called exactly once on the owner thread right before this |
+ // object is destroyed or when the owner thread is destroyed, |
+ // whichever comes first. Overridden by WeakHandle<T> (which also |
+ // calls WeakHandleCoreBase::CleanupOnOwnerThread()). |
+ virtual void CleanupOnOwnerThread(); |
+ |
+ // May be called on any thread. |
+ void PostToOwnerThread(const tracked_objects::Location& from_here, |
const base::Closure& fn) const; |
- template <typename T> |
- void DeleteOnOwnerThread(const tracked_objects::Location& from_here, |
- const T* ptr) const { |
- if (IsOnOwnerThread()) { |
- delete ptr; |
- } else { |
- ignore_result(message_loop_proxy_->DeleteSoon(from_here, ptr)); |
- } |
- } |
- |
private: |
- const scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; |
+ friend struct WeakHandleCoreBaseTraits; |
+ |
+ // May be called on any thread, but only via |
+ // WeakHandleCoreBaseTraits::Destruct(). Destroys and deletes this |
+ // object. |
+ void Destroy(); |
+ |
+ // Calls CleanupOnOwnerThread() and deletes |this|. Must be called |
+ // on the owner thread via Destroy(). |
+ void CleanupAndDestroyOnOwnerThread(); |
+ |
+ // May be read on any thread, but should only be dereferenced on the |
+ // owner thread. |
+ MessageLoop* const owner_loop_; |
+ |
+ // May be used on any thread. |
+ const scoped_refptr<base::MessageLoopProxy> owner_loop_proxy_; |
+ |
+ // Should only be read on the owner thread or in the destructor. |
+ // Used only for CHECKs. |
+ bool destroyed_on_owner_thread_; |
DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase); |
}; |
// WeakHandleCore<T> contains all the logic for WeakHandle<T>. |
template <typename T> |
-class WeakHandleCore |
- : public WeakHandleCoreBase, |
- public base::RefCountedThreadSafe<WeakHandleCore<T> > { |
+class WeakHandleCore : public WeakHandleCoreBase { |
public: |
// Must be called on |ptr|'s owner thread, which is assumed to be |
// the current thread. |
explicit WeakHandleCore(const base::WeakPtr<T>& ptr) |
: ptr_(new base::WeakPtr<T>(ptr)) {} |
- // May be destroyed on any thread. |
- ~WeakHandleCore() { |
- DeleteOnOwnerThread(FROM_HERE, ptr_); |
- } |
- |
// Must be called on |ptr_|'s owner thread. |
- const base::WeakPtr<T>& Get() const { |
+ base::WeakPtr<T> Get() const { |
CHECK(IsOnOwnerThread()); |
- return *ptr_; |
+ return ptr_ ? *ptr_ : base::WeakPtr<T>(); |
} |
// Call(...) may be called on any thread, but all its arguments |
@@ -155,7 +183,7 @@ class WeakHandleCore |
template <typename U> |
void Call(const tracked_objects::Location& from_here, |
void (U::*fn)(void)) const { |
- PostOnOwnerThread( |
+ PostToOwnerThread( |
from_here, |
Bind(&WeakHandleCore::template DoCall0<U>, this, fn)); |
} |
@@ -164,7 +192,7 @@ class WeakHandleCore |
void Call(const tracked_objects::Location& from_here, |
void (U::*fn)(A1), |
typename ParamTraits<A1>::ForwardType a1) const { |
- PostOnOwnerThread( |
+ PostToOwnerThread( |
from_here, |
Bind(&WeakHandleCore::template DoCall1<U, A1>, |
this, fn, a1)); |
@@ -175,7 +203,7 @@ class WeakHandleCore |
void (U::*fn)(A1, A2), |
typename ParamTraits<A1>::ForwardType a1, |
typename ParamTraits<A2>::ForwardType a2) const { |
- PostOnOwnerThread( |
+ PostToOwnerThread( |
from_here, |
Bind(&WeakHandleCore::template DoCall2<U, A1, A2>, |
this, fn, a1, a2)); |
@@ -187,7 +215,7 @@ class WeakHandleCore |
typename ParamTraits<A1>::ForwardType a1, |
typename ParamTraits<A2>::ForwardType a2, |
typename ParamTraits<A3>::ForwardType a3) const { |
- PostOnOwnerThread( |
+ PostToOwnerThread( |
from_here, |
Bind(&WeakHandleCore::template DoCall3<U, A1, A2, A3>, |
this, fn, a1, a2, a3)); |
@@ -200,14 +228,29 @@ class WeakHandleCore |
typename ParamTraits<A2>::ForwardType a2, |
typename ParamTraits<A3>::ForwardType a3, |
typename ParamTraits<A4>::ForwardType a4) const { |
- PostOnOwnerThread( |
+ PostToOwnerThread( |
from_here, |
Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>, |
this, fn, a1, a2, a3, a4)); |
} |
+ protected: |
+ // Must be called on |ptr_|'s owner thread exactly once. |
+ virtual void CleanupOnOwnerThread() OVERRIDE { |
+ CHECK(IsOnOwnerThread()); |
+ CHECK(ptr_); |
+ delete ptr_; |
+ ptr_ = NULL; |
+ WeakHandleCoreBase::CleanupOnOwnerThread(); |
+ } |
+ |
private: |
- friend class base::RefCountedThreadSafe<WeakHandleCore<T> >; |
+ // May be called on any thread. |
+ ~WeakHandleCore() { |
+ // It is safe to read |ptr_| here even if we're not on the owner |
+ // thread (see comments on base::AtomicRefCountDecN()). |
+ CHECK(!ptr_); |
+ } |
// GCC 4.2.1 on OS X gets confused if all the DoCall functions are |
// named the same, so we distinguish them. |
@@ -215,20 +258,20 @@ class WeakHandleCore |
template <typename U> |
void DoCall0(void (U::*fn)(void)) const { |
CHECK(IsOnOwnerThread()); |
- if (!ptr_->get()) { |
+ if (!Get()) { |
return; |
} |
- (ptr_->get()->*fn)(); |
+ (Get()->*fn)(); |
} |
template <typename U, typename A1> |
void DoCall1(void (U::*fn)(A1), |
typename ParamTraits<A1>::ForwardType a1) const { |
CHECK(IsOnOwnerThread()); |
- if (!ptr_->get()) { |
+ if (!Get()) { |
return; |
} |
- (ptr_->get()->*fn)(a1); |
+ (Get()->*fn)(a1); |
} |
template <typename U, typename A1, typename A2> |
@@ -236,10 +279,10 @@ class WeakHandleCore |
typename ParamTraits<A1>::ForwardType a1, |
typename ParamTraits<A2>::ForwardType a2) const { |
CHECK(IsOnOwnerThread()); |
- if (!ptr_->get()) { |
+ if (!Get()) { |
return; |
} |
- (ptr_->get()->*fn)(a1, a2); |
+ (Get()->*fn)(a1, a2); |
} |
template <typename U, typename A1, typename A2, typename A3> |
@@ -248,10 +291,10 @@ class WeakHandleCore |
typename ParamTraits<A2>::ForwardType a2, |
typename ParamTraits<A3>::ForwardType a3) const { |
CHECK(IsOnOwnerThread()); |
- if (!ptr_->get()) { |
+ if (!Get()) { |
return; |
} |
- (ptr_->get()->*fn)(a1, a2, a3); |
+ (Get()->*fn)(a1, a2, a3); |
} |
template <typename U, typename A1, typename A2, typename A3, typename A4> |
@@ -261,13 +304,14 @@ class WeakHandleCore |
typename ParamTraits<A3>::ForwardType a3, |
typename ParamTraits<A4>::ForwardType a4) const { |
CHECK(IsOnOwnerThread()); |
- if (!ptr_->get()) { |
+ if (!Get()) { |
return; |
} |
- (ptr_->get()->*fn)(a1, a2, a3, a4); |
+ (Get()->*fn)(a1, a2, a3, a4); |
} |
- // Must be used and destroyed only on the owner thread. |
+ // Must be dereferenced and destroyed only on the owner thread. |
+ // Must be read only on the owner thread or the destructor. |
base::WeakPtr<T>* ptr_; |
DISALLOW_COPY_AND_ASSIGN(WeakHandleCore); |