diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-25 23:34:34 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-25 23:34:34 +0000 |
commit | 59326aacf6020c3cfa8978a334c36b2dcc1a99bb (patch) | |
tree | 698940cee180d498131c98b9efbb2de30b642161 /base | |
parent | 754f7e974507e71f6ac40eec66bcb73f13d868c6 (diff) | |
download | chromium_src-59326aacf6020c3cfa8978a334c36b2dcc1a99bb.zip chromium_src-59326aacf6020c3cfa8978a334c36b2dcc1a99bb.tar.gz chromium_src-59326aacf6020c3cfa8978a334c36b2dcc1a99bb.tar.bz2 |
Implement ScopedRunnableMethodFactory using WeakPtr.
This required some changes to WeakPtr to support the addition
of WeakPtrFactory::HasWeakPtrs(), which is used to implement
ScopedRunnableMethodFactory::empty().
Now, the WeakReferenceOwner just holds a pointer to the Flag
class, and the Flag holds a back-pointer that it can use to
clear the WeakReferenceOwner's pointer when the Flag is
destroyed. I use the null'ness of this back-pointer in place
of the bool member that was previously used to indicate if the
WeakReference is valid.
It was also necessary to expose a HasOneRef method on
RefCounted. I included one on RefCountedThreadSafe for
completeness.
Finally, I switched HttpCache over to using WeakPtr instead
of RevocableStore so that I could delete RevocableStore.
(I'm making this change to consolidate similar functionality.)
R=abarth
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/235027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27287 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gyp | 2 | ||||
-rw-r--r-- | base/ref_counted.cc | 5 | ||||
-rw-r--r-- | base/ref_counted.h | 6 | ||||
-rw-r--r-- | base/revocable_store.cc | 47 | ||||
-rw-r--r-- | base/revocable_store.h | 74 | ||||
-rw-r--r-- | base/task.h | 113 | ||||
-rw-r--r-- | base/weak_ptr.h | 80 | ||||
-rw-r--r-- | base/weak_ptr_unittest.cc | 12 |
8 files changed, 101 insertions, 238 deletions
diff --git a/base/base.gyp b/base/base.gyp index bca5794..4e09866 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -244,8 +244,6 @@ 'registry.h', 'resource_util.cc', 'resource_util.h', - 'revocable_store.cc', - 'revocable_store.h', 'scoped_bstr_win.cc', 'scoped_bstr_win.h', 'scoped_cftyperef.h', diff --git a/base/ref_counted.cc b/base/ref_counted.cc index d278b3b..d272567 100644 --- a/base/ref_counted.cc +++ b/base/ref_counted.cc @@ -83,6 +83,11 @@ bool RefCountedThreadSafeBase::Release() { return false; } +bool RefCountedThreadSafeBase::HasOneRef() const { + return AtomicRefCountIsOne( + &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_); +} + } // namespace subtle } // namespace base diff --git a/base/ref_counted.h b/base/ref_counted.h index 79f9f55..097d16e 100644 --- a/base/ref_counted.h +++ b/base/ref_counted.h @@ -13,6 +13,9 @@ namespace base { namespace subtle { class RefCountedBase { + public: + bool HasOneRef() const { return ref_count_ == 1; } + protected: RefCountedBase(); ~RefCountedBase(); @@ -34,6 +37,9 @@ class RefCountedBase { }; class RefCountedThreadSafeBase { + public: + bool HasOneRef() const; + protected: RefCountedThreadSafeBase(); ~RefCountedThreadSafeBase(); diff --git a/base/revocable_store.cc b/base/revocable_store.cc deleted file mode 100644 index 400b2dd..0000000 --- a/base/revocable_store.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2008 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 "base/revocable_store.h" - -#include "base/logging.h" - -RevocableStore::Revocable::Revocable(RevocableStore* store) - : store_reference_(store->owning_reference_) { - // We AddRef() the owning reference. - DCHECK(store_reference_->store()); - store_reference_->store()->Add(this); -} - -RevocableStore::Revocable::~Revocable() { - if (!revoked()) { - // Notify the store of our destruction. - --(store_reference_->store()->count_); - } -} - -RevocableStore::RevocableStore() : count_(0) { - // Create a new owning reference. - owning_reference_ = new StoreRef(this); -} - -RevocableStore::~RevocableStore() { - // Revoke all the items in the store. - owning_reference_->set_store(NULL); -} - -void RevocableStore::Add(Revocable* item) { - DCHECK(!item->revoked()); - ++count_; -} - -void RevocableStore::RevokeAll() { - // We revoke all the existing items in the store and reset our count. - owning_reference_->set_store(NULL); - count_ = 0; - - // Then we create a new owning reference for new items that get added. - // This Release()s the old owning reference, allowing it to be freed after - // all the items that were in the store are eventually destroyed. - owning_reference_ = new StoreRef(this); -} diff --git a/base/revocable_store.h b/base/revocable_store.h deleted file mode 100644 index b0f1f31..0000000 --- a/base/revocable_store.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2006-2008 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. - -#ifndef BASE_REVOCABLE_STORE_H_ -#define BASE_REVOCABLE_STORE_H_ - -#include "base/ref_counted.h" - -// |RevocableStore| is a container of items that can be removed from the store. -class RevocableStore { - public: - // A |StoreRef| is used to link the |RevocableStore| to its items. There is - // one StoreRef per store, and each item holds a reference to it. If the - // store wishes to revoke its items, it sets |store_| to null. Items are - // permitted to release their reference to the |StoreRef| when they no longer - // require the store. - class StoreRef : public base::RefCounted<StoreRef> { - public: - StoreRef(RevocableStore* store) : store_(store) { } - - void set_store(RevocableStore* store) { store_ = store; } - RevocableStore* store() const { return store_; } - - private: - RevocableStore* store_; - - DISALLOW_EVIL_CONSTRUCTORS(StoreRef); - }; - - // An item in the store. On construction, the object adds itself to the - // store. - class Revocable { - public: - Revocable(RevocableStore* store); - ~Revocable(); - - // This item has been revoked if it no longer has a pointer to the store. - bool revoked() const { return !store_reference_->store(); } - - private: - // We hold a reference to the store through this ref pointer. We release - // this reference on destruction. - scoped_refptr<StoreRef> store_reference_; - - DISALLOW_EVIL_CONSTRUCTORS(Revocable); - }; - - RevocableStore(); - ~RevocableStore(); - - // Revokes all the items in the store. - void RevokeAll(); - - // Returns true if there are no items in the store. - bool empty() const { return count_ == 0; } - - private: - friend class Revocable; - - // Adds an item to the store. To add an item to the store, construct it - // with a pointer to the store. - void Add(Revocable* item); - - // This is the reference the unrevoked items in the store hold. - scoped_refptr<StoreRef> owning_reference_; - - // The number of unrevoked items in the store. - int count_; - - DISALLOW_EVIL_CONSTRUCTORS(RevocableStore); -}; - -#endif // BASE_REVOCABLE_STORE_H_ diff --git a/base/task.h b/base/task.h index 447bfab..c827681 100644 --- a/base/task.h +++ b/base/task.h @@ -6,9 +6,9 @@ #define BASE_TASK_H_ #include "base/non_thread_safe.h" -#include "base/revocable_store.h" #include "base/tracked.h" #include "base/tuple.h" +#include "base/weak_ptr.h" // Task ------------------------------------------------------------------------ // @@ -71,73 +71,31 @@ class CancelableTask : public Task { // } // }; -// A ScopedTaskFactory produces tasks of type |TaskType| and prevents them from -// running after it is destroyed. -template<class TaskType> -class ScopedTaskFactory : public RevocableStore { - public: - ScopedTaskFactory() { } - - // Create a new task. - inline TaskType* NewTask() { - return new TaskWrapper(this); - } - - class TaskWrapper : public TaskType, public NonThreadSafe { - public: - explicit TaskWrapper(RevocableStore* store) : revocable_(store) { } - - virtual void Run() { - if (!revocable_.revoked()) - TaskType::Run(); - } - - private: - Revocable revocable_; - - DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper); - }; - - private: - DISALLOW_EVIL_CONSTRUCTORS(ScopedTaskFactory); -}; - // A ScopedRunnableMethodFactory creates runnable methods for a specified // object. This is particularly useful for generating callbacks for // non-reference counted objects when the factory is a member of the object. template<class T> -class ScopedRunnableMethodFactory : public RevocableStore { +class ScopedRunnableMethodFactory { public: - explicit ScopedRunnableMethodFactory(T* object) : object_(object) { } + explicit ScopedRunnableMethodFactory(T* object) : weak_factory_(object) { + } template <class Method> inline Task* NewRunnableMethod(Method method) { - typedef typename ScopedTaskFactory<RunnableMethod< - Method, Tuple0> >::TaskWrapper TaskWrapper; - - TaskWrapper* task = new TaskWrapper(this); - task->Init(object_, method, MakeTuple()); - return task; + return new RunnableMethod<Method, Tuple0>( + weak_factory_.GetWeakPtr(), method, MakeTuple()); } template <class Method, class A> inline Task* NewRunnableMethod(Method method, const A& a) { - typedef typename ScopedTaskFactory<RunnableMethod< - Method, Tuple1<A> > >::TaskWrapper TaskWrapper; - - TaskWrapper* task = new TaskWrapper(this); - task->Init(object_, method, MakeTuple(a)); - return task; + return new RunnableMethod<Method, Tuple1<A> >( + weak_factory_.GetWeakPtr(), method, MakeTuple(a)); } template <class Method, class A, class B> inline Task* NewRunnableMethod(Method method, const A& a, const B& b) { - typedef typename ScopedTaskFactory<RunnableMethod< - Method, Tuple2<A, B> > >::TaskWrapper TaskWrapper; - - TaskWrapper* task = new TaskWrapper(this); - task->Init(object_, method, MakeTuple(a, b)); - return task; + return new RunnableMethod<Method, Tuple2<A, B> >( + weak_factory_.GetWeakPtr(), method, MakeTuple(a, b)); } template <class Method, class A, class B, class C> @@ -145,12 +103,8 @@ class ScopedRunnableMethodFactory : public RevocableStore { const A& a, const B& b, const C& c) { - typedef typename ScopedTaskFactory<RunnableMethod< - Method, Tuple3<A, B, C> > >::TaskWrapper TaskWrapper; - - TaskWrapper* task = new TaskWrapper(this); - task->Init(object_, method, MakeTuple(a, b, c)); - return task; + return new RunnableMethod<Method, Tuple3<A, B, C> >( + weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c)); } template <class Method, class A, class B, class C, class D> @@ -159,12 +113,8 @@ class ScopedRunnableMethodFactory : public RevocableStore { const B& b, const C& c, const D& d) { - typedef typename ScopedTaskFactory<RunnableMethod< - Method, Tuple4<A, B, C, D> > >::TaskWrapper TaskWrapper; - - TaskWrapper* task = new TaskWrapper(this); - task->Init(object_, method, MakeTuple(a, b, c, d)); - return task; + return new RunnableMethod<Method, Tuple4<A, B, C, D> >( + weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d)); } template <class Method, class A, class B, class C, class D, class E> @@ -174,40 +124,39 @@ class ScopedRunnableMethodFactory : public RevocableStore { const C& c, const D& d, const E& e) { - typedef typename ScopedTaskFactory<RunnableMethod< - Method, Tuple5<A, B, C, D, E> > >::TaskWrapper TaskWrapper; - - TaskWrapper* task = new TaskWrapper(this); - task->Init(object_, method, MakeTuple(a, b, c, d, e)); - return task; + return new RunnableMethod<Method, Tuple5<A, B, C, D, E> >( + weak_factory_.GetWeakPtr(), method, MakeTuple(a, b, c, d, e)); } + void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); } + + bool empty() const { return !weak_factory_.HasWeakPtrs(); } + protected: template <class Method, class Params> class RunnableMethod : public Task { public: - RunnableMethod() { } - - void Init(T* obj, Method meth, const Params& params) { - obj_ = obj; - meth_ = meth; - params_ = params; + RunnableMethod(const base::WeakPtr<T>& obj, Method meth, const Params& params) + : obj_(obj), + meth_(meth), + params_(params) { } - virtual void Run() { DispatchToMethod(obj_, meth_, params_); } + virtual void Run() { + if (obj_) + DispatchToMethod(obj_.get(), meth_, params_); + } private: - T* obj_; + base::WeakPtr<T> obj_; Method meth_; Params params_; - DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod); + DISALLOW_COPY_AND_ASSIGN(RunnableMethod); }; private: - T* object_; - - DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory); + base::WeakPtrFactory<T> weak_factory_; }; // General task implementations ------------------------------------------------ diff --git a/base/weak_ptr.h b/base/weak_ptr.h index 2fd670b..98b5870 100644 --- a/base/weak_ptr.h +++ b/base/weak_ptr.h @@ -63,63 +63,70 @@ namespace internal { class WeakReference { public: - void EnsureInitialized() { - // Lazy initialization helps faciliate the NonThreadSafe debug checks. - if (!flag_) { - flag_ = new Flag(); - flag_->data = true; - } - } - - void Invalidate() { - if (flag_) { - DCHECK(flag_->CalledOnValidThread()); - flag_->data = false; + class Flag : public RefCounted<Flag>, public NonThreadSafe { + public: + Flag(Flag** handle) : handle_(handle) { } - } - bool is_valid() const { - if (flag_) { - DCHECK(flag_->CalledOnValidThread()); - return flag_->data; + ~Flag() { + if (handle_) + *handle_ = NULL; } - return false; - } - private: - // A reference counted boolean that is true when the weak reference is valid - // and false otherwise. - class Flag : public RefCountedData<bool>, public NonThreadSafe { - public: void AddRef() { DCHECK(CalledOnValidThread()); - RefCountedData<bool>::AddRef(); + RefCounted<Flag>::AddRef(); } void Release() { DCHECK(CalledOnValidThread()); - RefCountedData<bool>::Release(); + RefCounted<Flag>::Release(); } + + void Invalidate() { handle_ = NULL; } + bool is_valid() const { return handle_ != NULL; } + + private: + Flag** handle_; }; + WeakReference() {} + WeakReference(Flag* flag) : flag_(flag) {} + + bool is_valid() const { return flag_ && flag_->is_valid(); } + + private: scoped_refptr<Flag> flag_; }; class WeakReferenceOwner { public: + WeakReferenceOwner() : flag_(NULL) { + } + ~WeakReferenceOwner() { - ref_.Invalidate(); + Invalidate(); } - const WeakReference& GetRef() const { - ref_.EnsureInitialized(); - return ref_; + WeakReference GetRef() const { + if (!flag_) + flag_ = new WeakReference::Flag(&flag_); + return WeakReference(flag_); } - void Invalidate() { ref_.Invalidate(); } + bool HasRefs() const { + return flag_ != NULL; + } + + void Invalidate() { + if (flag_) { + flag_->Invalidate(); + flag_ = NULL; + } + } private: - mutable WeakReference ref_; + mutable WeakReference::Flag* flag_; }; // This class simplifies the implementation of WeakPtr's type conversion @@ -231,7 +238,14 @@ class WeakPtrFactory { } // Call this method to invalidate all existing weak pointers. - void InvalidateWeakPtrs() { weak_reference_owner_.Invalidate(); } + void InvalidateWeakPtrs() { + weak_reference_owner_.Invalidate(); + } + + // Call this method to determine if any weak pointers exist. + bool HasWeakPtrs() const { + return weak_reference_owner_.HasRefs(); + } private: internal::WeakReferenceOwner weak_reference_owner_; diff --git a/base/weak_ptr_unittest.cc b/base/weak_ptr_unittest.cc index 80c277b..4f53358 100644 --- a/base/weak_ptr_unittest.cc +++ b/base/weak_ptr_unittest.cc @@ -96,8 +96,20 @@ TEST(WeakPtrTest, InvalidateWeakPtrs) { WeakPtrFactory<int> factory(&data); WeakPtr<int> ptr = factory.GetWeakPtr(); EXPECT_EQ(&data, ptr.get()); + EXPECT_TRUE(factory.HasWeakPtrs()); factory.InvalidateWeakPtrs(); EXPECT_EQ(NULL, ptr.get()); + EXPECT_FALSE(factory.HasWeakPtrs()); +} + +TEST(WeakPtrTest, HasWeakPtrs) { + int data; + WeakPtrFactory<int> factory(&data); + { + WeakPtr<int> ptr = factory.GetWeakPtr(); + EXPECT_TRUE(factory.HasWeakPtrs()); + } + EXPECT_FALSE(factory.HasWeakPtrs()); } TEST(WeakPtrTest, SingleThreaded1) { |