| 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);
|
|
|