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_UTIL_WEAK_HANDLE_H_ 48 #define SYNC_UTIL_WEAK_HANDLE_H_ 49 50 #include <cstddef> 51 52 #include "base/basictypes.h" 53 #include "base/bind.h" 54 #include "base/callback_forward.h" 55 #include "base/compiler_specific.h" 56 #include "base/gtest_prod_util.h" 57 #include "base/location.h" 58 #include "base/logging.h" 59 #include "base/memory/ref_counted.h" 60 #include "base/memory/weak_ptr.h" 61 #include "sync/base/sync_export.h" 62 63 namespace base { 64 class MessageLoopProxy; 65 } // namespace base 66 67 namespace tracked_objects { 68 class Location; 69 } // namespace tracked_objects 70 71 namespace syncer { 72 73 template <typename T> class WeakHandle; 74 75 namespace internal { 76 // These classes are part of the WeakHandle implementation. DO NOT 77 // USE THESE CLASSES DIRECTLY YOURSELF. 78 79 // Adapted from base/callback_internal.h. 80 81 template <typename T> 82 struct ParamTraits { 83 typedef const T& ForwardType; 84 }; 85 86 template <typename T> 87 struct ParamTraits<T&> { 88 typedef T& ForwardType; 89 }; 90 91 template <typename T, size_t n> 92 struct ParamTraits<T[n]> { 93 typedef const T* ForwardType; 94 }; 95 96 template <typename T> 97 struct ParamTraits<T[]> { 98 typedef const T* ForwardType; 99 }; 100 101 // Base class for WeakHandleCore<T> to avoid template bloat. Handles 102 // the interaction with the owner thread and its message loop. 103 class SYNC_EXPORT WeakHandleCoreBase { 104 public: 105 // Assumes the current thread is the owner thread. 106 WeakHandleCoreBase(); 107 108 // May be called on any thread. 109 bool IsOnOwnerThread() const; 110 111 protected: 112 // May be destroyed on any thread. 113 ~WeakHandleCoreBase(); 114 115 // May be called on any thread. 116 void PostToOwnerThread(const tracked_objects::Location& from_here, 117 const base::Closure& fn) const; 118 119 private: 120 // May be used on any thread. 121 const scoped_refptr<base::MessageLoopProxy> owner_loop_proxy_; 122 123 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase); 124 }; 125 126 // WeakHandleCore<T> contains all the logic for WeakHandle<T>. 127 template <typename T> 128 class WeakHandleCore 129 : public WeakHandleCoreBase, 130 public base::RefCountedThreadSafe<WeakHandleCore<T> > { 131 public: 132 // Must be called on |ptr|'s owner thread, which is assumed to be 133 // the current thread. 134 explicit WeakHandleCore(const base::WeakPtr<T>& ptr) : ptr_(ptr) {} 135 136 // Must be called on |ptr_|'s owner thread. 137 base::WeakPtr<T> Get() const { 138 CHECK(IsOnOwnerThread()); 139 return ptr_; 140 } 141 142 // Call(...) may be called on any thread, but all its arguments 143 // should be safe to be bound and copied across threads. 144 145 template <typename U> 146 void Call(const tracked_objects::Location& from_here, 147 void (U::*fn)(void)) const { 148 PostToOwnerThread( 149 from_here, 150 Bind(&WeakHandleCore::template DoCall0<U>, this, fn)); 151 } 152 153 template <typename U, typename A1> 154 void Call(const tracked_objects::Location& from_here, 155 void (U::*fn)(A1), 156 typename ParamTraits<A1>::ForwardType a1) const { 157 PostToOwnerThread( 158 from_here, 159 Bind(&WeakHandleCore::template DoCall1<U, A1>, 160 this, fn, a1)); 161 } 162 163 template <typename U, typename A1, typename A2> 164 void Call(const tracked_objects::Location& from_here, 165 void (U::*fn)(A1, A2), 166 typename ParamTraits<A1>::ForwardType a1, 167 typename ParamTraits<A2>::ForwardType a2) const { 168 PostToOwnerThread( 169 from_here, 170 Bind(&WeakHandleCore::template DoCall2<U, A1, A2>, 171 this, fn, a1, a2)); 172 } 173 174 template <typename U, typename A1, typename A2, typename A3> 175 void Call(const tracked_objects::Location& from_here, 176 void (U::*fn)(A1, A2, A3), 177 typename ParamTraits<A1>::ForwardType a1, 178 typename ParamTraits<A2>::ForwardType a2, 179 typename ParamTraits<A3>::ForwardType a3) const { 180 PostToOwnerThread( 181 from_here, 182 Bind(&WeakHandleCore::template DoCall3<U, A1, A2, A3>, 183 this, fn, a1, a2, a3)); 184 } 185 186 template <typename U, typename A1, typename A2, typename A3, typename A4> 187 void Call(const tracked_objects::Location& from_here, 188 void (U::*fn)(A1, A2, A3, A4), 189 typename ParamTraits<A1>::ForwardType a1, 190 typename ParamTraits<A2>::ForwardType a2, 191 typename ParamTraits<A3>::ForwardType a3, 192 typename ParamTraits<A4>::ForwardType a4) const { 193 PostToOwnerThread( 194 from_here, 195 Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>, 196 this, fn, a1, a2, a3, a4)); 197 } 198 199 private: 200 friend class base::RefCountedThreadSafe<WeakHandleCore<T> >; 201 202 // May be destroyed on any thread. 203 ~WeakHandleCore() {} 204 205 // GCC 4.2.1 on OS X gets confused if all the DoCall functions are 206 // named the same, so we distinguish them. 207 208 template <typename U> 209 void DoCall0(void (U::*fn)(void)) const { 210 CHECK(IsOnOwnerThread()); 211 if (!Get()) { 212 return; 213 } 214 (Get().get()->*fn)(); 215 } 216 217 template <typename U, typename A1> 218 void DoCall1(void (U::*fn)(A1), 219 typename ParamTraits<A1>::ForwardType a1) const { 220 CHECK(IsOnOwnerThread()); 221 if (!Get()) { 222 return; 223 } 224 (Get().get()->*fn)(a1); 225 } 226 227 template <typename U, typename A1, typename A2> 228 void DoCall2(void (U::*fn)(A1, A2), 229 typename ParamTraits<A1>::ForwardType a1, 230 typename ParamTraits<A2>::ForwardType a2) const { 231 CHECK(IsOnOwnerThread()); 232 if (!Get()) { 233 return; 234 } 235 (Get().get()->*fn)(a1, a2); 236 } 237 238 template <typename U, typename A1, typename A2, typename A3> 239 void DoCall3(void (U::*fn)(A1, A2, A3), 240 typename ParamTraits<A1>::ForwardType a1, 241 typename ParamTraits<A2>::ForwardType a2, 242 typename ParamTraits<A3>::ForwardType a3) const { 243 CHECK(IsOnOwnerThread()); 244 if (!Get()) { 245 return; 246 } 247 (Get().get()->*fn)(a1, a2, a3); 248 } 249 250 template <typename U, typename A1, typename A2, typename A3, typename A4> 251 void DoCall4(void (U::*fn)(A1, A2, A3, A4), 252 typename ParamTraits<A1>::ForwardType a1, 253 typename ParamTraits<A2>::ForwardType a2, 254 typename ParamTraits<A3>::ForwardType a3, 255 typename ParamTraits<A4>::ForwardType a4) const { 256 CHECK(IsOnOwnerThread()); 257 if (!Get()) { 258 return; 259 } 260 (Get().get()->*fn)(a1, a2, a3, a4); 261 } 262 263 // Must be dereferenced only on the owner thread. May be destroyed 264 // from any thread. 265 base::WeakPtr<T> ptr_; 266 267 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore); 268 }; 269 270 } // namespace internal 271 272 // May be destroyed on any thread. 273 // Copying and assignment are welcome. 274 template <typename T> 275 class WeakHandle { 276 public: 277 // Creates an uninitialized WeakHandle. 278 WeakHandle() {} 279 280 // Creates an initialized WeakHandle from |ptr|. 281 explicit WeakHandle(const base::WeakPtr<T>& ptr) 282 : core_(new internal::WeakHandleCore<T>(ptr)) {} 283 284 // Allow conversion from WeakHandle<U> to WeakHandle<T> if U is 285 // convertible to T, but we *must* be on |other|'s owner thread. 286 // Note that this doesn't override the regular copy constructor, so 287 // that one can be called on any thread. 288 template <typename U> 289 WeakHandle(const WeakHandle<U>& other) // NOLINT 290 : core_( 291 other.IsInitialized() ? 292 new internal::WeakHandleCore<T>(other.Get()) : 293 NULL) {} 294 295 // Returns true iff this WeakHandle is initialized. Note that being 296 // initialized isn't a guarantee that the underlying object is still 297 // alive. 298 bool IsInitialized() const { 299 return core_.get() != NULL; 300 } 301 302 // Resets to an uninitialized WeakHandle. 303 void Reset() { 304 core_ = NULL; 305 } 306 307 // Must be called only on the underlying object's owner thread. 308 base::WeakPtr<T> Get() const { 309 CHECK(IsInitialized()); 310 CHECK(core_->IsOnOwnerThread()); 311 return core_->Get(); 312 } 313 314 // Call(...) may be called on any thread, but all its arguments 315 // should be safe to be bound and copied across threads. 316 317 template <typename U> 318 void Call(const tracked_objects::Location& from_here, 319 void (U::*fn)(void)) const { 320 CHECK(IsInitialized()); 321 core_->Call(from_here, fn); 322 } 323 324 template <typename U, typename A1> 325 void Call(const tracked_objects::Location& from_here, 326 void (U::*fn)(A1), 327 typename internal::ParamTraits<A1>::ForwardType a1) const { 328 CHECK(IsInitialized()); 329 core_->Call(from_here, fn, a1); 330 } 331 332 template <typename U, typename A1, typename A2> 333 void Call(const tracked_objects::Location& from_here, 334 void (U::*fn)(A1, A2), 335 typename internal::ParamTraits<A1>::ForwardType a1, 336 typename internal::ParamTraits<A2>::ForwardType a2) const { 337 CHECK(IsInitialized()); 338 core_->Call(from_here, fn, a1, a2); 339 } 340 341 template <typename U, typename A1, typename A2, typename A3> 342 void Call(const tracked_objects::Location& from_here, 343 void (U::*fn)(A1, A2, A3), 344 typename internal::ParamTraits<A1>::ForwardType a1, 345 typename internal::ParamTraits<A2>::ForwardType a2, 346 typename internal::ParamTraits<A3>::ForwardType a3) const { 347 CHECK(IsInitialized()); 348 core_->Call(from_here, fn, a1, a2, a3); 349 } 350 351 template <typename U, typename A1, typename A2, typename A3, typename A4> 352 void Call(const tracked_objects::Location& from_here, 353 void (U::*fn)(A1, A2, A3, A4), 354 typename internal::ParamTraits<A1>::ForwardType a1, 355 typename internal::ParamTraits<A2>::ForwardType a2, 356 typename internal::ParamTraits<A3>::ForwardType a3, 357 typename internal::ParamTraits<A4>::ForwardType a4) const { 358 CHECK(IsInitialized()); 359 core_->Call(from_here, fn, a1, a2, a3, a4); 360 } 361 362 private: 363 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest, 364 TypeConversionConstructor); 365 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest, 366 TypeConversionConstructorAssignment); 367 368 scoped_refptr<internal::WeakHandleCore<T> > core_; 369 }; 370 371 // Makes a WeakHandle from a WeakPtr. 372 template <typename T> 373 WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) { 374 return WeakHandle<T>(ptr); 375 } 376 377 } // namespace syncer 378 379 #endif // SYNC_UTIL_WEAK_HANDLE_H_ 380