| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Weak handles provides a way to refer to weak pointers from another | |
| 6 // thread. This is useful because it is not safe to reference a weak | |
| 7 // pointer from a thread other than the thread on which it was | |
| 8 // created. | |
| 9 // | |
| 10 // Weak handles can be passed across threads, so for example, you can | |
| 11 // use them to do the "real" work on one thread and get notified on | |
| 12 // another thread: | |
| 13 // | |
| 14 // class FooIOWorker { | |
| 15 // public: | |
| 16 // FooIOWorker(const WeakHandle<Foo>& foo) : foo_(foo) {} | |
| 17 // | |
| 18 // void OnIOStart() { | |
| 19 // foo_.Call(FROM_HERE, &Foo::OnIOStart); | |
| 20 // } | |
| 21 // | |
| 22 // void OnIOEvent(IOEvent e) { | |
| 23 // foo_.Call(FROM_HERE, &Foo::OnIOEvent, e); | |
| 24 // } | |
| 25 // | |
| 26 // void OnIOError(IOError err) { | |
| 27 // foo_.Call(FROM_HERE, &Foo::OnIOError, err); | |
| 28 // } | |
| 29 // | |
| 30 // private: | |
| 31 // const WeakHandle<Foo> foo_; | |
| 32 // }; | |
| 33 // | |
| 34 // class Foo : public SupportsWeakPtr<Foo>, public NonThreadSafe { | |
| 35 // public: | |
| 36 // Foo() { | |
| 37 // SpawnFooIOWorkerOnIOThread(base::MakeWeakHandle(AsWeakPtr())); | |
| 38 // } | |
| 39 // | |
| 40 // /* Will always be called on the correct thread, and only if this | |
| 41 // object hasn't been destroyed. */ | |
| 42 // void OnIOStart() { DCHECK(CalledOnValidThread(); ... } | |
| 43 // void OnIOEvent(IOEvent e) { DCHECK(CalledOnValidThread(); ... } | |
| 44 // void OnIOError(IOError err) { DCHECK(CalledOnValidThread(); ... } | |
| 45 // }; | |
| 46 | |
| 47 #ifndef SYNC_INTERNAL_API_PUBLIC_UTIL_WEAK_HANDLE_H_ | |
| 48 #define SYNC_INTERNAL_API_PUBLIC_UTIL_WEAK_HANDLE_H_ | |
| 49 | |
| 50 #include <cstddef> | |
| 51 #include <utility> | |
| 52 | |
| 53 #include "base/bind.h" | |
| 54 #include "base/compiler_specific.h" | |
| 55 #include "base/gtest_prod_util.h" | |
| 56 #include "base/location.h" | |
| 57 #include "base/logging.h" | |
| 58 #include "base/macros.h" | |
| 59 #include "base/memory/ref_counted.h" | |
| 60 #include "base/memory/weak_ptr.h" | |
| 61 #include "base/single_thread_task_runner.h" | |
| 62 #include "sync/base/sync_export.h" | |
| 63 | |
| 64 namespace tracked_objects { | |
| 65 class Location; | |
| 66 } // namespace tracked_objects | |
| 67 | |
| 68 namespace syncer { | |
| 69 | |
| 70 template <typename T> class WeakHandle; | |
| 71 | |
| 72 namespace internal { | |
| 73 // These classes are part of the WeakHandle implementation. DO NOT | |
| 74 // USE THESE CLASSES DIRECTLY YOURSELF. | |
| 75 | |
| 76 // Base class for WeakHandleCore<T> to avoid template bloat. Handles | |
| 77 // the interaction with the owner thread and its message loop. | |
| 78 class SYNC_EXPORT WeakHandleCoreBase { | |
| 79 public: | |
| 80 // Assumes the current thread is the owner thread. | |
| 81 WeakHandleCoreBase(); | |
| 82 | |
| 83 // May be called on any thread. | |
| 84 bool IsOnOwnerThread() const; | |
| 85 | |
| 86 protected: | |
| 87 // May be destroyed on any thread. | |
| 88 ~WeakHandleCoreBase(); | |
| 89 | |
| 90 // May be called on any thread. | |
| 91 void PostToOwnerThread(const tracked_objects::Location& from_here, | |
| 92 const base::Closure& fn) const; | |
| 93 | |
| 94 private: | |
| 95 // May be used on any thread. | |
| 96 const scoped_refptr<base::SingleThreadTaskRunner> owner_loop_task_runner_; | |
| 97 | |
| 98 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase); | |
| 99 }; | |
| 100 | |
| 101 // WeakHandleCore<T> contains all the logic for WeakHandle<T>. | |
| 102 template <typename T> | |
| 103 class WeakHandleCore | |
| 104 : public WeakHandleCoreBase, | |
| 105 public base::RefCountedThreadSafe<WeakHandleCore<T> > { | |
| 106 public: | |
| 107 // Must be called on |ptr|'s owner thread, which is assumed to be | |
| 108 // the current thread. | |
| 109 explicit WeakHandleCore(const base::WeakPtr<T>& ptr) : ptr_(ptr) {} | |
| 110 | |
| 111 // Must be called on |ptr_|'s owner thread. | |
| 112 base::WeakPtr<T> Get() const { | |
| 113 CHECK(IsOnOwnerThread()); | |
| 114 return ptr_; | |
| 115 } | |
| 116 | |
| 117 // Call(...) may be called on any thread, but all its arguments | |
| 118 // should be safe to be bound and copied across threads. | |
| 119 template <typename Method, typename... Args> | |
| 120 void Call(const tracked_objects::Location& from_here, | |
| 121 Method method, Args&&... args) const { | |
| 122 PostToOwnerThread( | |
| 123 from_here, base::Bind(method, ptr_, std::forward<Args>(args)...)); | |
| 124 } | |
| 125 | |
| 126 private: | |
| 127 friend class base::RefCountedThreadSafe<WeakHandleCore<T> >; | |
| 128 | |
| 129 // May be destroyed on any thread. | |
| 130 ~WeakHandleCore() {} | |
| 131 | |
| 132 // Must be dereferenced only on the owner thread. May be destroyed | |
| 133 // from any thread. | |
| 134 base::WeakPtr<T> ptr_; | |
| 135 | |
| 136 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore); | |
| 137 }; | |
| 138 | |
| 139 } // namespace internal | |
| 140 | |
| 141 // May be destroyed on any thread. | |
| 142 // Copying and assignment are welcome. | |
| 143 template <typename T> | |
| 144 class WeakHandle { | |
| 145 public: | |
| 146 // Creates an uninitialized WeakHandle. | |
| 147 WeakHandle() {} | |
| 148 | |
| 149 // Creates an initialized WeakHandle from |ptr|. | |
| 150 explicit WeakHandle(const base::WeakPtr<T>& ptr) | |
| 151 : core_(new internal::WeakHandleCore<T>(ptr)) {} | |
| 152 | |
| 153 // Allow conversion from WeakHandle<U> to WeakHandle<T> if U is | |
| 154 // convertible to T, but we *must* be on |other|'s owner thread. | |
| 155 // Note that this doesn't override the regular copy constructor, so | |
| 156 // that one can be called on any thread. | |
| 157 template <typename U> | |
| 158 WeakHandle(const WeakHandle<U>& other) // NOLINT | |
| 159 : core_( | |
| 160 other.IsInitialized() ? | |
| 161 new internal::WeakHandleCore<T>(other.Get()) : | |
| 162 NULL) {} | |
| 163 | |
| 164 // Returns true iff this WeakHandle is initialized. Note that being | |
| 165 // initialized isn't a guarantee that the underlying object is still | |
| 166 // alive. | |
| 167 bool IsInitialized() const { | |
| 168 return core_.get() != NULL; | |
| 169 } | |
| 170 | |
| 171 // Resets to an uninitialized WeakHandle. | |
| 172 void Reset() { | |
| 173 core_ = NULL; | |
| 174 } | |
| 175 | |
| 176 // Must be called only on the underlying object's owner thread. | |
| 177 base::WeakPtr<T> Get() const { | |
| 178 CHECK(IsInitialized()); | |
| 179 CHECK(core_->IsOnOwnerThread()); | |
| 180 return core_->Get(); | |
| 181 } | |
| 182 | |
| 183 // Call(...) may be called on any thread, but all its arguments | |
| 184 // should be safe to be bound and copied across threads. | |
| 185 template <typename Method, typename... Args> | |
| 186 void Call(const tracked_objects::Location& from_here, | |
| 187 Method method, Args&&... args) const { | |
| 188 CHECK(IsInitialized()); | |
| 189 core_->Call(from_here, method, std::forward<Args>(args)...); | |
| 190 } | |
| 191 | |
| 192 private: | |
| 193 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest, | |
| 194 TypeConversionConstructor); | |
| 195 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest, | |
| 196 TypeConversionConstructorAssignment); | |
| 197 | |
| 198 scoped_refptr<internal::WeakHandleCore<T> > core_; | |
| 199 }; | |
| 200 | |
| 201 // Makes a WeakHandle from a WeakPtr. | |
| 202 template <typename T> | |
| 203 WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) { | |
| 204 return WeakHandle<T>(ptr); | |
| 205 } | |
| 206 | |
| 207 } // namespace syncer | |
| 208 | |
| 209 #endif // SYNC_INTERNAL_API_PUBLIC_UTIL_WEAK_HANDLE_H_ | |
| OLD | NEW |