diff options
-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 | ||||
-rw-r--r-- | net/http/http_cache.cc | 32 | ||||
-rw-r--r-- | net/http/http_cache.h | 6 |
10 files changed, 119 insertions, 258 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) { diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 6703661..c1c3478 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -168,13 +168,11 @@ HttpCache::ActiveEntry::~ActiveEntry() { //----------------------------------------------------------------------------- -class HttpCache::Transaction - : public HttpTransaction, public RevocableStore::Revocable { +class HttpCache::Transaction : public HttpTransaction { public: Transaction(HttpCache* cache, bool enable_range_support) - : RevocableStore::Revocable(&cache->transactions_), - request_(NULL), - cache_(cache), + : request_(NULL), + cache_(cache->AsWeakPtr()), entry_(NULL), network_trans_(NULL), callback_(NULL), @@ -382,7 +380,7 @@ class HttpCache::Transaction // If extra_headers specified a "if-modified-since" or "if-none-match", // |external_validation_| contains the value of that header. ValidationHeader external_validation_; - HttpCache* cache_; + base::WeakPtr<HttpCache> cache_; HttpCache::ActiveEntry* entry_; scoped_ptr<HttpTransaction> network_trans_; CompletionCallback* callback_; // Consumer's callback. @@ -407,7 +405,7 @@ class HttpCache::Transaction }; HttpCache::Transaction::~Transaction() { - if (!revoked()) { + if (cache_) { if (entry_) { bool cancel_request = reading_ && enable_range_support_; if (cancel_request && !partial_.get()) @@ -425,7 +423,7 @@ HttpCache::Transaction::~Transaction() { // We could still have a cache read in progress, so we just null the cache_ // pointer to signal that we are dead. See OnCacheReadCompleted. - cache_ = NULL; + cache_.reset(); } int HttpCache::Transaction::Start(const HttpRequestInfo* request, @@ -437,7 +435,7 @@ int HttpCache::Transaction::Start(const HttpRequestInfo* request, // ensure that we only have one asynchronous call at a time. DCHECK(!callback_); - if (revoked()) + if (!cache_) return ERR_UNEXPECTED; SetRequest(load_log, request); @@ -493,7 +491,7 @@ int HttpCache::Transaction::RestartIgnoringLastError( // ensure that we only have one asynchronous call at a time. DCHECK(!callback_); - if (revoked()) + if (!cache_) return ERR_UNEXPECTED; int rv = RestartNetworkRequest(); @@ -512,7 +510,7 @@ int HttpCache::Transaction::RestartWithCertificate( // ensure that we only have one asynchronous call at a time. DCHECK(!callback_); - if (revoked()) + if (!cache_) return ERR_UNEXPECTED; int rv = RestartNetworkRequestWithCertificate(client_cert); @@ -533,7 +531,7 @@ int HttpCache::Transaction::RestartWithAuth( // Ensure that we only have one asynchronous call at a time. DCHECK(!callback_); - if (revoked()) + if (!cache_) return ERR_UNEXPECTED; // Clear the intermediate response since we are going to start over. @@ -561,7 +559,7 @@ int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, DCHECK(!callback_); - if (revoked()) + if (!cache_) return ERR_UNEXPECTED; // If we have an intermediate auth response at this point, then it means the @@ -629,7 +627,7 @@ uint64 HttpCache::Transaction::GetUploadProgress() const { int HttpCache::Transaction::AddToEntry() { ActiveEntry* entry = NULL; - if (revoked()) + if (!cache_) return ERR_UNEXPECTED; if (mode_ == WRITE) { @@ -1396,7 +1394,7 @@ void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { int HttpCache::Transaction::DoNetworkReadCompleted(int result) { DCHECK(mode_ & WRITE || mode_ == NONE); - if (revoked()) + if (!cache_) return HandleResult(ERR_UNEXPECTED); AppendResponseDataToEntry(read_buf_, result); @@ -1431,7 +1429,7 @@ int HttpCache::Transaction::DoCacheReadCompleted(int result) { DCHECK(cache_); cache_read_callback_->Release(); // Balance the AddRef() from Start(). - if (revoked()) + if (!cache_) return HandleResult(ERR_UNEXPECTED); if (partial_.get()) @@ -1467,7 +1465,7 @@ int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { void HttpCache::Transaction::OnNetworkInfoAvailable(int result) { DCHECK(result != ERR_IO_PENDING); - if (revoked()) { + if (!cache_) { HandleResult(ERR_UNEXPECTED); return; } diff --git a/net/http/http_cache.h b/net/http/http_cache.h index 652f3a4..15163b07 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h @@ -21,6 +21,7 @@ #include "base/hash_tables.h" #include "base/scoped_ptr.h" #include "base/task.h" +#include "base/weak_ptr.h" #include "net/base/cache_type.h" #include "net/http/http_transaction_factory.h" @@ -38,7 +39,8 @@ class HttpResponseInfo; class ProxyService; class SSLConfigService; -class HttpCache : public HttpTransactionFactory { +class HttpCache : public HttpTransactionFactory, + public base::SupportsWeakPtr<HttpCache> { public: ~HttpCache(); @@ -206,8 +208,6 @@ class HttpCache : public HttpTransactionFactory { typedef base::hash_map<std::string, int> PlaybackCacheMap; scoped_ptr<PlaybackCacheMap> playback_cache_map_; - RevocableStore transactions_; - DISALLOW_COPY_AND_ASSIGN(HttpCache); }; |