diff options
Diffstat (limited to 'base/memory/weak_ptr.h')
-rw-r--r-- | base/memory/weak_ptr.h | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h new file mode 100644 index 0000000..0c6b4a7 --- /dev/null +++ b/base/memory/weak_ptr.h @@ -0,0 +1,255 @@ +// Copyright (c) 2011 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. + +// Weak pointers help in cases where you have many objects referring back to a +// shared object and you wish for the lifetime of the shared object to not be +// bound to the lifetime of the referrers. In other words, this is useful when +// reference counting is not a good fit. +// +// A common alternative to weak pointers is to have the shared object hold a +// list of all referrers, and then when the shared object is destroyed, it +// calls a method on the referrers to tell them to drop their references. This +// approach also requires the referrers to tell the shared object when they get +// destroyed so that the shared object can remove the referrer from its list of +// referrers. Such a solution works, but it is a bit complex. +// +// EXAMPLE: +// +// class Controller : public SupportsWeakPtr<Controller> { +// public: +// void SpawnWorker() { Worker::StartNew(AsWeakPtr()); } +// void WorkComplete(const Result& result) { ... } +// }; +// +// class Worker { +// public: +// static void StartNew(const WeakPtr<Controller>& controller) { +// Worker* worker = new Worker(controller); +// // Kick off asynchronous processing... +// } +// private: +// Worker(const WeakPtr<Controller>& controller) +// : controller_(controller) {} +// void DidCompleteAsynchronousProcessing(const Result& result) { +// if (controller_) +// controller_->WorkComplete(result); +// } +// WeakPtr<Controller> controller_; +// }; +// +// Given the above classes, a consumer may allocate a Controller object, call +// SpawnWorker several times, and then destroy the Controller object before all +// of the workers have completed. Because the Worker class only holds a weak +// pointer to the Controller, we don't have to worry about the Worker +// dereferencing the Controller back pointer after the Controller has been +// destroyed. +// +// WARNING: weak pointers are not threadsafe!!! You must only use a WeakPtr +// instance on thread where it was created. + +#ifndef BASE_MEMORY_WEAK_PTR_H_ +#define BASE_MEMORY_WEAK_PTR_H_ +#pragma once + +#include "base/base_api.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/threading/thread_checker.h" + +namespace base { + +namespace internal { +// These classes are part of the WeakPtr implementation. +// DO NOT USE THESE CLASSES DIRECTLY YOURSELF. + +class BASE_API WeakReference { + public: + // While Flag is bound to a specific thread, it may be deleted from another + // via base::WeakPtr::~WeakPtr(). + class Flag : public RefCountedThreadSafe<Flag> { + public: + explicit Flag(Flag** handle); + + void Invalidate(); + bool IsValid() const; + + void DetachFromThread() { thread_checker_.DetachFromThread(); } + + private: + friend class base::RefCountedThreadSafe<Flag>; + + ~Flag(); + + ThreadChecker thread_checker_; + Flag** handle_; + }; + + WeakReference(); + WeakReference(Flag* flag); + ~WeakReference(); + + bool is_valid() const; + + private: + scoped_refptr<Flag> flag_; +}; + +class BASE_API WeakReferenceOwner { + public: + WeakReferenceOwner(); + ~WeakReferenceOwner(); + + WeakReference GetRef() const; + + bool HasRefs() const { + return flag_ != NULL; + } + + void Invalidate(); + + // Indicates that this object will be used on another thread from now on. + void DetachFromThread() { + if (flag_) flag_->DetachFromThread(); + } + + private: + mutable WeakReference::Flag* flag_; +}; + +// This class simplifies the implementation of WeakPtr's type conversion +// constructor by avoiding the need for a public accessor for ref_. A +// WeakPtr<T> cannot access the private members of WeakPtr<U>, so this +// base class gives us a way to access ref_ in a protected fashion. +class BASE_API WeakPtrBase { + public: + WeakPtrBase(); + ~WeakPtrBase(); + + protected: + WeakPtrBase(const WeakReference& ref); + + WeakReference ref_; +}; + +} // namespace internal + +template <typename T> class SupportsWeakPtr; +template <typename T> class WeakPtrFactory; + +// The WeakPtr class holds a weak reference to |T*|. +// +// This class is designed to be used like a normal pointer. You should always +// null-test an object of this class before using it or invoking a method that +// may result in the underlying object being destroyed. +// +// EXAMPLE: +// +// class Foo { ... }; +// WeakPtr<Foo> foo; +// if (foo) +// foo->method(); +// +template <typename T> +class WeakPtr : public internal::WeakPtrBase { + public: + WeakPtr() : ptr_(NULL) { + } + + // Allow conversion from U to T provided U "is a" T. + template <typename U> + WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.get()) { + } + + T* get() const { return ref_.is_valid() ? ptr_ : NULL; } + operator T*() const { return get(); } + + T* operator*() const { + DCHECK(get() != NULL); + return *get(); + } + T* operator->() const { + DCHECK(get() != NULL); + return get(); + } + + void reset() { + ref_ = internal::WeakReference(); + ptr_ = NULL; + } + + private: + friend class SupportsWeakPtr<T>; + friend class WeakPtrFactory<T>; + + WeakPtr(const internal::WeakReference& ref, T* ptr) + : WeakPtrBase(ref), ptr_(ptr) { + } + + // This pointer is only valid when ref_.is_valid() is true. Otherwise, its + // value is undefined (as opposed to NULL). + T* ptr_; +}; + +// A class may extend from SupportsWeakPtr to expose weak pointers to itself. +// This is useful in cases where you want others to be able to get a weak +// pointer to your class. It also has the property that you don't need to +// initialize it from your constructor. +template <class T> +class SupportsWeakPtr { + public: + SupportsWeakPtr() {} + + WeakPtr<T> AsWeakPtr() { + return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this)); + } + + // Indicates that this object will be used on another thread from now on. + void DetachFromThread() { + weak_reference_owner_.DetachFromThread(); + } + + private: + internal::WeakReferenceOwner weak_reference_owner_; + DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr); +}; + +// A class may alternatively be composed of a WeakPtrFactory and thereby +// control how it exposes weak pointers to itself. This is helpful if you only +// need weak pointers within the implementation of a class. This class is also +// useful when working with primitive types. For example, you could have a +// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. +template <class T> +class WeakPtrFactory { + public: + explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { + } + + WeakPtr<T> GetWeakPtr() { + return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_); + } + + // Call this method to invalidate all existing weak pointers. + void InvalidateWeakPtrs() { + weak_reference_owner_.Invalidate(); + } + + // Call this method to determine if any weak pointers exist. + bool HasWeakPtrs() const { + return weak_reference_owner_.HasRefs(); + } + + // Indicates that this object will be used on another thread from now on. + void DetachFromThread() { + weak_reference_owner_.DetachFromThread(); + } + + private: + internal::WeakReferenceOwner weak_reference_owner_; + T* ptr_; + DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); +}; + +} // namespace base + +#endif // BASE_MEMORY_WEAK_PTR_H_ |