summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authordarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-25 23:34:34 +0000
committerdarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-25 23:34:34 +0000
commit59326aacf6020c3cfa8978a334c36b2dcc1a99bb (patch)
tree698940cee180d498131c98b9efbb2de30b642161 /base
parent754f7e974507e71f6ac40eec66bcb73f13d868c6 (diff)
downloadchromium_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.gyp2
-rw-r--r--base/ref_counted.cc5
-rw-r--r--base/ref_counted.h6
-rw-r--r--base/revocable_store.cc47
-rw-r--r--base/revocable_store.h74
-rw-r--r--base/task.h113
-rw-r--r--base/weak_ptr.h80
-rw-r--r--base/weak_ptr_unittest.cc12
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) {