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 63namespace base { 64class MessageLoopProxy; 65} // namespace base 66 67namespace tracked_objects { 68class Location; 69} // namespace tracked_objects 70 71namespace syncer { 72 73template <typename T> class WeakHandle; 74 75namespace 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 81template <typename T> 82struct ParamTraits { 83 typedef const T& ForwardType; 84}; 85 86template <typename T> 87struct ParamTraits<T&> { 88 typedef T& ForwardType; 89}; 90 91template <typename T, size_t n> 92struct ParamTraits<T[n]> { 93 typedef const T* ForwardType; 94}; 95 96template <typename T> 97struct 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. 103class 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>. 127template <typename T> 128class 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. 274template <typename T> 275class 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. 372template <typename T> 373WeakHandle<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